mcli-framework 8.0.36__tar.gz → 8.0.38__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.
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/PKG-INFO +1 -1
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/pyproject.toml +1 -1
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/list_cmd.py +26 -2
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/services_cmd.py +4 -1
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/logger/logger.py +7 -7
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/script_loader.py +59 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/shell/shell.py +6 -6
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/toml/toml.py +1 -1
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/workflow.py +65 -26
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli_framework.egg-info/PKG-INFO +1 -1
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli_framework.egg-info/SOURCES.txt +1 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_self_cmd_utilities.py +1 -1
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/fixtures/command_fixtures.py +2 -2
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_custom_commands.py +5 -5
- mcli_framework-8.0.38/tests/unit/test_language_suffix.py +467 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/dependabot.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/dependency-review-config.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/workflows/build.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/workflows/ci.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/workflows/codeql.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/workflows/docs-links.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/workflows/publish-self-hosted.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/workflows/publish.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/workflows/release.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/workflows/security.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/.github/workflows/test.yml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/LICENSE +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/MANIFEST.in +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/README.md +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/llms-full.txt +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/llms.txt +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/mcli_rust/Cargo.toml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/mcli_rust/src/command_parser.rs +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/mcli_rust/src/file_watcher.rs +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/mcli_rust/src/lib.rs +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/mcli_rust/src/process_manager.rs +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/mcli_rust/src/tfidf.rs +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/setup.cfg +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/commands_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/completion_helpers.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/context_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/create_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/delete_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/edit_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/init_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/main.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/migrate_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/model/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/model/model.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/model_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/mv_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/new_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/remove_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/rm_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/search_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/sync_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/video/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/app/video/video.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/config.toml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/api/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/api/api.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/api/daemon_client.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/api/daemon_client_local.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/api/daemon_decorator.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/api/mcli_decorators.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/auth.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/aws_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/azure_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/credential_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/gcp_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/key_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/mcli_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/token_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/auth/token_util.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/config/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/config/config.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/constants/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/constants/commands.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/constants/defaults.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/constants/env.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/constants/messages.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/constants/paths.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/constants/scripts.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/constants/storage.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/custom_commands.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/discovery/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/discovery/command_discovery.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/erd/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/erd/erd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/erd/generate_graph.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/errors.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/feature_detection.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/files/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/files/files.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/folder_workflows.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/fs/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/fs/fs.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/ipfs_sync.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/lib.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/logger/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/logger/correlation.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/logger/structured.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/optional_deps.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/paths.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/performance/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/performance/optimizer.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/performance/rust_bridge.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/performance/uvloop_config.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/pickles/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/pickles/pickles.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/pyenv/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/pyenv/deps.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/pyenv/manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/pyenv/venv.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/script_sync.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/script_watcher.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/search/cached_vectorizer.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/secrets/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/secrets/commands.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/secrets/manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/secrets/repl.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/secrets/store.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/config.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/data_pipeline.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/health.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/lsh_client.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/redis_service.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/registry.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/state.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/services/supervisor.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/shell/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/shell/exceptions.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/templates/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/templates/command_templates.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/toml/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/types.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/ui/styling.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/ui/visual_effects.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/watcher/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/watcher/watcher.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/workflow_models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/lib/workspace_registry.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/app.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/middleware.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/admin_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/auth_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/backtest_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/data_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/model_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/monitoring_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/portfolio_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/prediction_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/trade_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/routers/websocket_router.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/api/schemas.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/auth/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/auth/auth_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/auth/models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/auth/permissions.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/backtesting/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/backtesting/backtest_engine.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/backtesting/performance_metrics.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/backtesting/run.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/cache.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/cli/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/cli/main.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/config/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/config/settings.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/configs/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/configs/dvc_config.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/configs/mlflow_config.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/configs/mlops_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/app.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/app_integrated.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/app_supabase.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/app_training.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/cli.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/common.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/components/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/components/charts.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/components/metrics.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/components/tables.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/overview.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/cicd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/debug_dependencies.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/gravity_viz.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/monte_carlo_predictions.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/predictions_enhanced.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/scrapers_and_logs.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/test_portfolio.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/trading.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/pages/workflows.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/streamlit_extras_utils.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/styles.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/utils.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/dashboard/warning_suppression.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/data_ingestion/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/data_ingestion/api_connectors.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/data_ingestion/data_pipeline.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/data_ingestion/stream_processor.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/database/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/database/migrations/env.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/database/models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/database/session.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/experimentation/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/experimentation/ab_testing.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/features/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/features/ensemble_features.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/features/recommendation_engine.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/features/stock_features.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/features/test_feature_engineering.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/logging.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/mlops/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/mlops/data_versioning.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/mlops/experiment_tracker.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/mlops/model_serving.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/mlops/pipeline_orchestrator.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/models/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/models/base_models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/models/ensemble_models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/models/recommendation_models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/models/test_models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/monitoring/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/monitoring/drift_detection.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/monitoring/metrics.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/optimization/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/optimization/optimize.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/optimization/portfolio_optimizer.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/predictions/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/predictions/monte_carlo.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/predictions/prediction_engine.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/preprocessing/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/preprocessing/data_cleaners.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/preprocessing/feature_extractors.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/preprocessing/ml_pipeline.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/preprocessing/test_preprocessing.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/scripts/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/scripts/populate_sample_data.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/serving/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/serving/serve.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/tasks.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/tests/test_integration.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/tests/test_training_dashboard.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/trading/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/trading/alpaca_client.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/trading/migrations.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/trading/models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/trading/paper_trading.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/trading/risk_management.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/trading/trading_service.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/training/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/training/train.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/ml/training/train_model.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/mygroup/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/mygroup/test_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/public/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/public/commands/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/public/oi/oi.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/public/public.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/completion_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/env_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/health_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/logs_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/migrate_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/self_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/store_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/test_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/self/workflows_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/storage/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/storage/backends/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/storage/backends/ipfs_backend.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/storage/base.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/storage/cache.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/storage/encryption.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/storage/factory.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/storage/registry.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/storage/storacha_cli.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/async_command_database.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/async_process_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/client.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/daemon.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/daemon_api.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/enhanced_daemon.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/process_cli.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/process_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/daemon/test_daemon.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/dashboard/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/dashboard/dashboard_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/doc_convert.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/docker/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/docker/docker.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/file/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/gcloud/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/gcloud/config.toml +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/gcloud/gcloud.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/git_commit/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/git_commit/ai_service.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/interview/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/lsh_integration.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/client.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/download_and_run_efficient_models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/lightweight_embedder.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/lightweight_model_server.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/lightweight_test.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/model_service.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/ollama_efficient_runner.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/openai_adapter.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/pdf_processor.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/test_efficient_runner.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/test_example.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/test_integration.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/model_service/test_new_features.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/notebook/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/notebook/command_loader.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/notebook/converter.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/notebook/executor.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/notebook/notebook_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/notebook/schema.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/notebook/validator.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/openai/openai.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/registry/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/registry/registry.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/repo/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/repo/repo.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/scheduler/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/scheduler/cron_parser.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/scheduler/job.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/scheduler/models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/scheduler/monitor.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/scheduler/persistence.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/scheduler/scheduler.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/scheduler/validation.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/search/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/secrets/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/secrets/secrets_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/storage/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/storage/storage_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/sync/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/sync/test_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/videos/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/wakatime/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli/workflow/wakatime/wakatime.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli_framework.egg-info/dependency_links.txt +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli_framework.egg-info/entry_points.txt +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli_framework.egg-info/requires.txt +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/src/mcli_framework.egg-info/top_level.txt +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_all_commands.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_app_logs_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_app_redis_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_logs_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_main_app.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_model_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_self_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_self_cmd_plugins.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_workflow_creation_commands.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_workflow_file.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_workflow_gcloud.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/cli/test_workflow_registry.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/conftest.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/e2e/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/e2e/test_complete_workflows.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/e2e/test_model_workflow.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/e2e/test_new_user_workflow.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/e2e/test_update_workflow.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/fixtures/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/fixtures/chat_fixtures.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/fixtures/cli_fixtures.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/fixtures/data_fixtures.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/fixtures/db_fixtures.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/fixtures/model_fixtures.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_all_commands_comprehensive.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_daemon_server.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_direct_file_execution.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_e2e_dashboard_lsh_supabase.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_flask_webapp.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_folder_workflows_integration.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_gcloud_services.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_ml_auth.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_ml_data_pipeline.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_ml_models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_ml_pipeline.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_module_imports.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_notebook_workflows.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_oi_service.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_repo_operations.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_scheduler_integration.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_service_registry.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_supabase_live_connection.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_video_processing.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_wakatime_api.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_webapp_full.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_workflow.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/integration/test_workflow_commands.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/performance/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/property/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/storage/__init__.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/storage/test_cache.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/storage/test_encryption.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/storage/test_storacha_cli.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_api_utils.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_async_process_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_auth_modules.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_bug_fixes.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_command_fixtures.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_config.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_correlation_logging.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_custom_commands_filtering.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_daemon_api.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_dashboard_components.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_dashboard_functions.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_dashboard_pages.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_dependencies.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_doc_convert_workflow.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_emulator_workflow.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_erd_generation.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_erd_generic.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_erd_imports.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_folder_workflows.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_git_commit_workflow.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_health_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_init_mv_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_ipfs_retry.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_lib_auth.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_lib_files.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_lib_utils.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_logger.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_ml_preprocessing.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_new_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_notebook_command_loader.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_notebook_executor.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_optional_deps.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_paths.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_pdf_compress.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_prediction_engine.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_pyenv.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_regression.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_scheduler.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_scheduler_cron_parser.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_scheduler_job.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_scheduler_models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_scheduler_monitor.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_scheduler_persistence.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_scheduler_validation.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_script_loader_options.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_security_command_injection.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_self_update.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_service_config.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_service_health.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_service_manager.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_service_state.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_services_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_shell_exceptions.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_shell_functions.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_shell_security.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_store_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_supabase_connection.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_supabase_pagination.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_sync_cmd.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_toml_utils.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_trading_imports.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_ui_rich.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_uv_compat.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_workflow_file_completion.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/test_workflow_models.py +0 -0
- {mcli_framework-8.0.36 → mcli_framework-8.0.38}/tests/unit/workflow/test_notebook.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcli-framework
|
|
3
|
-
Version: 8.0.
|
|
3
|
+
Version: 8.0.38
|
|
4
4
|
Summary: Portable workflow framework - transform any script into a versioned, schedulable command. Store in ~/.mcli/workflows/, version with lockfile, run as daemon or cron job.
|
|
5
5
|
Author-email: Luis Fernandez de la Vara <luis@lefv.io>
|
|
6
6
|
Maintainer-email: Luis Fernandez de la Vara <luis@lefv.io>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mcli-framework"
|
|
3
|
-
version = "8.0.
|
|
3
|
+
version = "8.0.38"
|
|
4
4
|
description = "Portable workflow framework - transform any script into a versioned, schedulable command. Store in ~/.mcli/workflows/, version with lockfile, run as daemon or cron job."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -111,6 +111,25 @@ def _list_workspaces(as_json: bool):
|
|
|
111
111
|
console.print(f"\n[dim]Total: {len(workspaces)} workspace(s)[/dim]")
|
|
112
112
|
|
|
113
113
|
|
|
114
|
+
def _apply_display_names(workflows: list[dict]) -> None:
|
|
115
|
+
"""Add 'display_name' key to workflows, using suffixed names for duplicate stems.
|
|
116
|
+
|
|
117
|
+
When multiple workflows share the same base name (e.g. backup.py and backup.sh),
|
|
118
|
+
their display names become 'backup:py' and 'backup:sh'. Unique names stay bare.
|
|
119
|
+
"""
|
|
120
|
+
from collections import Counter
|
|
121
|
+
|
|
122
|
+
from mcli.lib.script_loader import LANGUAGE_TO_SUFFIX
|
|
123
|
+
|
|
124
|
+
stem_counts = Counter(wf["name"] for wf in workflows)
|
|
125
|
+
for wf in workflows:
|
|
126
|
+
if stem_counts[wf["name"]] > 1:
|
|
127
|
+
suffix = LANGUAGE_TO_SUFFIX.get(wf.get("language", ""), "?")
|
|
128
|
+
wf["display_name"] = f"{wf['name']}:{suffix}"
|
|
129
|
+
else:
|
|
130
|
+
wf["display_name"] = wf["name"]
|
|
131
|
+
|
|
132
|
+
|
|
114
133
|
def _list_all_workflows(as_json: bool):
|
|
115
134
|
"""List workflows from all registered workspaces."""
|
|
116
135
|
from rich.panel import Panel
|
|
@@ -122,6 +141,7 @@ def _list_all_workflows(as_json: bool):
|
|
|
122
141
|
# Flatten for JSON output
|
|
123
142
|
flat_workflows = []
|
|
124
143
|
for workspace_name, workflows in all_workflows.items():
|
|
144
|
+
_apply_display_names(workflows)
|
|
125
145
|
for wf in workflows:
|
|
126
146
|
wf["workspace"] = workspace_name
|
|
127
147
|
flat_workflows.append(wf)
|
|
@@ -142,6 +162,8 @@ def _list_all_workflows(as_json: bool):
|
|
|
142
162
|
if not workflows:
|
|
143
163
|
continue
|
|
144
164
|
|
|
165
|
+
_apply_display_names(workflows)
|
|
166
|
+
|
|
145
167
|
table = Table(show_header=True, header_style="bold")
|
|
146
168
|
table.add_column("Name", style="cyan")
|
|
147
169
|
table.add_column("Description", style="white")
|
|
@@ -153,7 +175,7 @@ def _list_all_workflows(as_json: bool):
|
|
|
153
175
|
if len(desc) > 50:
|
|
154
176
|
desc = desc[:47] + "..."
|
|
155
177
|
table.add_row(
|
|
156
|
-
wf["
|
|
178
|
+
wf["display_name"],
|
|
157
179
|
desc,
|
|
158
180
|
wf.get("language", "?"),
|
|
159
181
|
wf.get("version", "1.0.0"),
|
|
@@ -202,6 +224,8 @@ def _list_scope_workflows(is_global: bool, as_json: bool):
|
|
|
202
224
|
except Exception as e:
|
|
203
225
|
logger.debug(f"Failed to get info for {script_path}: {e}")
|
|
204
226
|
|
|
227
|
+
_apply_display_names(workflows)
|
|
228
|
+
|
|
205
229
|
if as_json:
|
|
206
230
|
click.echo(json.dumps({"workflows": workflows, "total": len(workflows)}, indent=2))
|
|
207
231
|
return
|
|
@@ -226,7 +250,7 @@ def _list_scope_workflows(is_global: bool, as_json: bool):
|
|
|
226
250
|
if len(desc) > 50:
|
|
227
251
|
desc = desc[:47] + "..."
|
|
228
252
|
table.add_row(
|
|
229
|
-
wf["
|
|
253
|
+
wf["display_name"],
|
|
230
254
|
desc,
|
|
231
255
|
wf.get("language", "?"),
|
|
232
256
|
wf.get("version", "1.0.0"),
|
|
@@ -37,7 +37,10 @@ def _get_config_from_state(name: str) -> ServiceConfig:
|
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
@click.group(
|
|
40
|
+
@click.group(
|
|
41
|
+
"services",
|
|
42
|
+
help="\U0001f6e0\ufe0f Manage long-running services (start/stop/restart, health, logs).",
|
|
43
|
+
)
|
|
41
44
|
def services():
|
|
42
45
|
"""Service lifecycle management."""
|
|
43
46
|
pass
|
|
@@ -25,9 +25,9 @@ class McliLogger:
|
|
|
25
25
|
_runtime_tracing_enabled: bool = False
|
|
26
26
|
_system_tracing_enabled: bool = False
|
|
27
27
|
_system_trace_interval: int = 5 # Default to check every 5 seconds
|
|
28
|
-
_system_trace_process_ids:
|
|
28
|
+
_system_trace_process_ids: set[int] = set() # Process IDs to monitor
|
|
29
29
|
_system_trace_thread: Optional[threading.Thread] = None
|
|
30
|
-
_excluded_modules:
|
|
30
|
+
_excluded_modules: set[str] = set()
|
|
31
31
|
_trace_level: int = 0 # 0=off, 1=function calls, 2=line by line, 3=verbose
|
|
32
32
|
_system_trace_level: int = 0 # 0=off, 1=basic, 2=detailed
|
|
33
33
|
|
|
@@ -54,7 +54,7 @@ class McliLogger:
|
|
|
54
54
|
|
|
55
55
|
@classmethod
|
|
56
56
|
def enable_runtime_tracing(
|
|
57
|
-
cls, level: int = 1, excluded_modules: Optional[
|
|
57
|
+
cls, level: int = 1, excluded_modules: Optional[list[str]] = None
|
|
58
58
|
) -> None:
|
|
59
59
|
"""
|
|
60
60
|
Enable Python interpreter runtime tracing.
|
|
@@ -279,7 +279,7 @@ class McliLogger:
|
|
|
279
279
|
|
|
280
280
|
return True
|
|
281
281
|
|
|
282
|
-
def _get_process_info(self, pid: int, detailed: bool = False) ->
|
|
282
|
+
def _get_process_info(self, pid: int, detailed: bool = False) -> dict[str, Any]:
|
|
283
283
|
"""Get information about a process given its PID."""
|
|
284
284
|
try:
|
|
285
285
|
# Check if process exists
|
|
@@ -339,7 +339,7 @@ class McliLogger:
|
|
|
339
339
|
except Exception as e:
|
|
340
340
|
return {"pid": pid, "status": "ERROR", "error": str(e)}
|
|
341
341
|
|
|
342
|
-
def _format_process_info(self, info:
|
|
342
|
+
def _format_process_info(self, info: dict[str, Any]) -> str:
|
|
343
343
|
"""Format process information for logging."""
|
|
344
344
|
if info.get("status") == "NOT_FOUND":
|
|
345
345
|
return f"Process {info['pid']} no longer exists"
|
|
@@ -475,7 +475,7 @@ class McliLogger:
|
|
|
475
475
|
if self._trace_level >= 3:
|
|
476
476
|
# Include source line in verbose mode
|
|
477
477
|
try:
|
|
478
|
-
with open(filename
|
|
478
|
+
with open(filename) as f:
|
|
479
479
|
lines = f.readlines()
|
|
480
480
|
source = (
|
|
481
481
|
lines[lineno - 1].strip()
|
|
@@ -543,7 +543,7 @@ def get_system_trace_logger() -> logging.Logger:
|
|
|
543
543
|
return McliLogger.get_system_trace_logger()
|
|
544
544
|
|
|
545
545
|
|
|
546
|
-
def enable_runtime_tracing(level: int = 1, excluded_modules: Optional[
|
|
546
|
+
def enable_runtime_tracing(level: int = 1, excluded_modules: Optional[list[str]] = None) -> None:
|
|
547
547
|
"""
|
|
548
548
|
Enable Python interpreter runtime tracing.
|
|
549
549
|
|
|
@@ -43,6 +43,54 @@ SUPPORTED_EXTENSIONS: dict[str, str] = {
|
|
|
43
43
|
".ipynb": "ipynb",
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
# Maps user-facing suffixes to canonical language names
|
|
47
|
+
LANGUAGE_SUFFIXES: dict[str, str] = {
|
|
48
|
+
"py": "python",
|
|
49
|
+
"python": "python",
|
|
50
|
+
"sh": "shell",
|
|
51
|
+
"shell": "shell",
|
|
52
|
+
"bash": "shell",
|
|
53
|
+
"js": "javascript",
|
|
54
|
+
"javascript": "javascript",
|
|
55
|
+
"ts": "typescript",
|
|
56
|
+
"typescript": "typescript",
|
|
57
|
+
"ipynb": "ipynb",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Reverse map: canonical language name → short suffix for display
|
|
61
|
+
LANGUAGE_TO_SUFFIX: dict[str, str] = {
|
|
62
|
+
"python": "py",
|
|
63
|
+
"shell": "sh",
|
|
64
|
+
"javascript": "js",
|
|
65
|
+
"typescript": "ts",
|
|
66
|
+
"ipynb": "ipynb",
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def parse_command_name(cmd_name: str) -> tuple[str, Optional[str]]:
|
|
71
|
+
"""Parse 'name:suffix' into (base_name, language_or_None).
|
|
72
|
+
|
|
73
|
+
Uses rsplit so that names containing colons still work correctly.
|
|
74
|
+
Unknown suffixes are treated as part of the base name (no language filter).
|
|
75
|
+
|
|
76
|
+
Examples:
|
|
77
|
+
>>> parse_command_name("backup:py")
|
|
78
|
+
("backup", "python")
|
|
79
|
+
>>> parse_command_name("backup")
|
|
80
|
+
("backup", None)
|
|
81
|
+
>>> parse_command_name("my:cmd:sh")
|
|
82
|
+
("my:cmd", "shell")
|
|
83
|
+
>>> parse_command_name("backup:xyz")
|
|
84
|
+
("backup:xyz", None)
|
|
85
|
+
"""
|
|
86
|
+
if ":" in cmd_name:
|
|
87
|
+
base, suffix = cmd_name.rsplit(":", 1)
|
|
88
|
+
language = LANGUAGE_SUFFIXES.get(suffix.lower())
|
|
89
|
+
if language:
|
|
90
|
+
return base, language
|
|
91
|
+
return cmd_name, None
|
|
92
|
+
|
|
93
|
+
|
|
46
94
|
# Shebang patterns for language detection
|
|
47
95
|
SHEBANG_PATTERNS: dict[str, re.Pattern] = {
|
|
48
96
|
"python": re.compile(r"#!/.*python"),
|
|
@@ -136,6 +184,17 @@ class ScriptLoader:
|
|
|
136
184
|
|
|
137
185
|
return sorted(scripts, key=lambda p: p.stem)
|
|
138
186
|
|
|
187
|
+
def find_scripts_by_stem(self, stem: str) -> list[Path]:
|
|
188
|
+
"""Return all discovered scripts whose stem matches the given name.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
stem: The base name (without extension) to search for
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
List of matching script paths, sorted by name
|
|
195
|
+
"""
|
|
196
|
+
return [p for p in self.discover_scripts() if p.stem == stem]
|
|
197
|
+
|
|
139
198
|
def detect_language(self, script_path: Path) -> str:
|
|
140
199
|
"""
|
|
141
200
|
Detect script language from shebang or extension.
|
|
@@ -39,7 +39,7 @@ logger = get_logger(__name__)
|
|
|
39
39
|
MAX_COMMAND_LENGTH = 100000
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
def shell_exec(script_path: str, function_name: str, *args) -> Optional[
|
|
42
|
+
def shell_exec(script_path: str, function_name: str, *args) -> Optional[dict[str, Any]]:
|
|
43
43
|
"""Execute a shell script function with security checks and better error handling.
|
|
44
44
|
|
|
45
45
|
Args:
|
|
@@ -176,7 +176,7 @@ def fatal_error(msg: str) -> None:
|
|
|
176
176
|
|
|
177
177
|
|
|
178
178
|
def execute_os_command(
|
|
179
|
-
command: Union[str,
|
|
179
|
+
command: Union[str, list[str]],
|
|
180
180
|
fail_on_error: bool = True,
|
|
181
181
|
stdin: Optional[str] = None,
|
|
182
182
|
timeout: Optional[int] = None,
|
|
@@ -294,12 +294,12 @@ def execute_os_command(
|
|
|
294
294
|
|
|
295
295
|
|
|
296
296
|
def execute_command_safe(
|
|
297
|
-
args:
|
|
297
|
+
args: list[str],
|
|
298
298
|
fail_on_error: bool = True,
|
|
299
299
|
stdin: Optional[str] = None,
|
|
300
300
|
timeout: Optional[int] = None,
|
|
301
301
|
cwd: Optional[str] = None,
|
|
302
|
-
env: Optional[
|
|
302
|
+
env: Optional[dict[str, str]] = None,
|
|
303
303
|
check_executable: bool = True,
|
|
304
304
|
) -> str:
|
|
305
305
|
"""Execute a command safely without shell interpolation.
|
|
@@ -414,11 +414,11 @@ def execute_command_safe(
|
|
|
414
414
|
|
|
415
415
|
|
|
416
416
|
def execute_command_with_result(
|
|
417
|
-
args:
|
|
417
|
+
args: list[str],
|
|
418
418
|
stdin: Optional[str] = None,
|
|
419
419
|
timeout: Optional[int] = None,
|
|
420
420
|
cwd: Optional[str] = None,
|
|
421
|
-
env: Optional[
|
|
421
|
+
env: Optional[dict[str, str]] = None,
|
|
422
422
|
) -> CommandResult:
|
|
423
423
|
"""Execute a command and return structured result (never raises on non-zero exit).
|
|
424
424
|
|
|
@@ -26,7 +26,7 @@ def read_from_toml(file_path: str, key: str) -> Optional[Any]:
|
|
|
26
26
|
# Fall back to the third-party 'toml' package for earlier Python versions.
|
|
27
27
|
import toml
|
|
28
28
|
|
|
29
|
-
with open(file_path,
|
|
29
|
+
with open(file_path, encoding="utf-8") as file:
|
|
30
30
|
config_data = toml.load(file)
|
|
31
31
|
|
|
32
32
|
# Return the value for the provided key, or None if the key is not found.
|
|
@@ -40,10 +40,17 @@ class ScopedWorkflowsGroup(click.Group):
|
|
|
40
40
|
return get_custom_commands_dir(global_mode=is_global)
|
|
41
41
|
|
|
42
42
|
def list_commands(self, ctx):
|
|
43
|
-
"""List available commands based on scope.
|
|
43
|
+
"""List available commands based on scope.
|
|
44
|
+
|
|
45
|
+
When multiple scripts share a stem (e.g. backup.py and backup.sh),
|
|
46
|
+
emits suffixed names like backup:py and backup:sh so that tab completion
|
|
47
|
+
offers distinct entries for each language variant.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
from collections import Counter
|
|
44
51
|
|
|
45
52
|
from mcli.lib.logger.logger import get_logger
|
|
46
|
-
from mcli.lib.script_loader import ScriptLoader
|
|
53
|
+
from mcli.lib.script_loader import LANGUAGE_TO_SUFFIX, ScriptLoader
|
|
47
54
|
|
|
48
55
|
logger = get_logger()
|
|
49
56
|
|
|
@@ -60,17 +67,26 @@ class ScopedWorkflowsGroup(click.Group):
|
|
|
60
67
|
|
|
61
68
|
# Load native script commands
|
|
62
69
|
script_commands = []
|
|
70
|
+
script_stems = set()
|
|
63
71
|
if workflows_dir.exists():
|
|
64
72
|
loader = ScriptLoader(workflows_dir)
|
|
65
73
|
scripts = loader.discover_scripts()
|
|
66
74
|
|
|
75
|
+
# Count how many scripts share each stem
|
|
76
|
+
stem_counts = Counter(sp.stem for sp in scripts)
|
|
77
|
+
|
|
67
78
|
for script_path in scripts:
|
|
68
79
|
name = script_path.stem
|
|
69
|
-
# Validate the command can be loaded
|
|
70
80
|
try:
|
|
71
81
|
command = loader.load_command(script_path)
|
|
72
82
|
if command:
|
|
73
|
-
|
|
83
|
+
if stem_counts[name] > 1:
|
|
84
|
+
lang = loader.detect_language(script_path)
|
|
85
|
+
suffix = LANGUAGE_TO_SUFFIX.get(lang, script_path.suffix.lstrip("."))
|
|
86
|
+
script_commands.append(f"{name}:{suffix}")
|
|
87
|
+
else:
|
|
88
|
+
script_commands.append(name)
|
|
89
|
+
script_stems.add(name)
|
|
74
90
|
else:
|
|
75
91
|
logger.debug(f"Script '{name}' could not be loaded as a command")
|
|
76
92
|
except Exception as e:
|
|
@@ -91,7 +107,7 @@ class ScopedWorkflowsGroup(click.Group):
|
|
|
91
107
|
|
|
92
108
|
cmd_name = cmd_data.get("name")
|
|
93
109
|
# Skip if already loaded as native script
|
|
94
|
-
if cmd_name in
|
|
110
|
+
if cmd_name in script_stems:
|
|
95
111
|
continue
|
|
96
112
|
|
|
97
113
|
# Validate the command can be loaded
|
|
@@ -112,14 +128,18 @@ class ScopedWorkflowsGroup(click.Group):
|
|
|
112
128
|
logger.debug(f"Could not load legacy JSON commands: {e}")
|
|
113
129
|
|
|
114
130
|
# Only return user-defined workflows (scripts + legacy JSON)
|
|
115
|
-
# This matches the behavior of `mcli list`.
|
|
116
|
-
|
|
117
131
|
return sorted(set(script_commands + legacy_commands))
|
|
118
132
|
|
|
119
133
|
def get_command(self, ctx, cmd_name):
|
|
120
|
-
"""Get a command by name, loading from appropriate scope.
|
|
134
|
+
"""Get a command by name, loading from appropriate scope.
|
|
135
|
+
|
|
136
|
+
Supports language suffix disambiguation: 'backup:py' loads the Python
|
|
137
|
+
version, 'backup:sh' loads the shell version. Bare names work when
|
|
138
|
+
unambiguous; when ambiguous, a warning is shown and the first match runs.
|
|
139
|
+
"""
|
|
140
|
+
from mcli.lib.constants.messages import WarningMessages
|
|
121
141
|
from mcli.lib.logger.logger import get_logger
|
|
122
|
-
from mcli.lib.script_loader import ScriptLoader
|
|
142
|
+
from mcli.lib.script_loader import LANGUAGE_TO_SUFFIX, ScriptLoader, parse_command_name
|
|
123
143
|
|
|
124
144
|
logger = get_logger()
|
|
125
145
|
|
|
@@ -134,24 +154,43 @@ class ScopedWorkflowsGroup(click.Group):
|
|
|
134
154
|
logger.warning(f"Workspace not found: {workspace}")
|
|
135
155
|
return None
|
|
136
156
|
|
|
157
|
+
# Parse language suffix (e.g. "backup:py" → base="backup", lang="python")
|
|
158
|
+
base_name, lang_filter = parse_command_name(cmd_name)
|
|
159
|
+
|
|
137
160
|
# Try to load as native script first
|
|
138
161
|
if workflows_dir.exists():
|
|
139
162
|
loader = ScriptLoader(workflows_dir)
|
|
140
|
-
|
|
163
|
+
matches = loader.find_scripts_by_stem(base_name)
|
|
141
164
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
165
|
+
if lang_filter:
|
|
166
|
+
# Filter to requested language
|
|
167
|
+
matches = [p for p in matches if loader.detect_language(p) == lang_filter]
|
|
168
|
+
|
|
169
|
+
if len(matches) == 1:
|
|
170
|
+
try:
|
|
171
|
+
command = loader.load_command(matches[0])
|
|
172
|
+
if command:
|
|
173
|
+
logger.debug(f"Loaded native script command: {cmd_name}")
|
|
174
|
+
return command
|
|
175
|
+
except Exception as e:
|
|
176
|
+
logger.debug(f"Failed to load script '{cmd_name}': {e}")
|
|
177
|
+
elif len(matches) > 1 and not lang_filter:
|
|
178
|
+
# Ambiguous — show hint, pick first
|
|
179
|
+
from mcli.lib.ui.styling import warning
|
|
180
|
+
|
|
181
|
+
suffixes = [LANGUAGE_TO_SUFFIX.get(loader.detect_language(p), "?") for p in matches]
|
|
182
|
+
options = ", ".join(f"{base_name}:{s}" for s in suffixes)
|
|
183
|
+
warning(WarningMessages.AMBIGUOUS_COMMAND.format(name=base_name, options=options))
|
|
184
|
+
try:
|
|
185
|
+
command = loader.load_command(matches[0])
|
|
186
|
+
if command:
|
|
187
|
+
logger.debug(f"Loaded first match for ambiguous command: {base_name}")
|
|
188
|
+
return command
|
|
189
|
+
except Exception as e:
|
|
190
|
+
logger.debug(f"Failed to load script '{base_name}': {e}")
|
|
191
|
+
|
|
192
|
+
# Fall back to legacy JSON commands (use base_name for lookup)
|
|
193
|
+
lookup_name = base_name if lang_filter else cmd_name
|
|
155
194
|
try:
|
|
156
195
|
from mcli.lib.custom_commands import get_command_manager
|
|
157
196
|
|
|
@@ -161,7 +200,7 @@ class ScopedWorkflowsGroup(click.Group):
|
|
|
161
200
|
# Find the workflow command
|
|
162
201
|
for command_data in commands:
|
|
163
202
|
# Accept both "workflow" and "workflows" for backward compatibility
|
|
164
|
-
if command_data.get("name") ==
|
|
203
|
+
if command_data.get("name") == lookup_name and command_data.get("group") in [
|
|
165
204
|
"workflow",
|
|
166
205
|
"workflows",
|
|
167
206
|
]:
|
|
@@ -174,9 +213,9 @@ class ScopedWorkflowsGroup(click.Group):
|
|
|
174
213
|
else:
|
|
175
214
|
manager.register_command_with_click(command_data, temp_group)
|
|
176
215
|
|
|
177
|
-
cmd = temp_group.commands.get(
|
|
216
|
+
cmd = temp_group.commands.get(lookup_name)
|
|
178
217
|
if cmd:
|
|
179
|
-
logger.debug(f"Loaded legacy JSON command: {
|
|
218
|
+
logger.debug(f"Loaded legacy JSON command: {lookup_name}")
|
|
180
219
|
return cmd
|
|
181
220
|
except Exception as e:
|
|
182
221
|
logger.debug(f"Could not load legacy command '{cmd_name}': {e}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcli-framework
|
|
3
|
-
Version: 8.0.
|
|
3
|
+
Version: 8.0.38
|
|
4
4
|
Summary: Portable workflow framework - transform any script into a versioned, schedulable command. Store in ~/.mcli/workflows/, version with lockfile, run as daemon or cron job.
|
|
5
5
|
Author-email: Luis Fernandez de la Vara <luis@lefv.io>
|
|
6
6
|
Maintainer-email: Luis Fernandez de la Vara <luis@lefv.io>
|
|
@@ -431,6 +431,7 @@ tests/unit/test_git_commit_workflow.py
|
|
|
431
431
|
tests/unit/test_health_cmd.py
|
|
432
432
|
tests/unit/test_init_mv_cmd.py
|
|
433
433
|
tests/unit/test_ipfs_retry.py
|
|
434
|
+
tests/unit/test_language_suffix.py
|
|
434
435
|
tests/unit/test_lib_auth.py
|
|
435
436
|
tests/unit/test_lib_files.py
|
|
436
437
|
tests/unit/test_lib_utils.py
|
|
@@ -29,7 +29,7 @@ class MockCommandResponse:
|
|
|
29
29
|
duration_ms: float = 10.0
|
|
30
30
|
exception: Optional[Exception] = None
|
|
31
31
|
|
|
32
|
-
def to_result(self, command: Optional[
|
|
32
|
+
def to_result(self, command: Optional[list[str]] = None) -> CommandResult:
|
|
33
33
|
"""Convert to a CommandResult object."""
|
|
34
34
|
return CommandResult(
|
|
35
35
|
returncode=self.returncode,
|
|
@@ -299,7 +299,7 @@ def capture_commands():
|
|
|
299
299
|
|
|
300
300
|
class CommandCapture:
|
|
301
301
|
def __init__(self):
|
|
302
|
-
self.commands:
|
|
302
|
+
self.commands: list[list[str]] = []
|
|
303
303
|
self._patches = []
|
|
304
304
|
|
|
305
305
|
def _capture(self, args, **kwargs):
|
|
@@ -63,7 +63,7 @@ class TestCustomCommandManager:
|
|
|
63
63
|
assert path.name == "test_cmd.json"
|
|
64
64
|
|
|
65
65
|
# Verify content
|
|
66
|
-
with open(path
|
|
66
|
+
with open(path) as f:
|
|
67
67
|
data = json.load(f)
|
|
68
68
|
|
|
69
69
|
assert data["name"] == "test_cmd"
|
|
@@ -156,7 +156,7 @@ class TestCustomCommandManager:
|
|
|
156
156
|
assert self.manager.lockfile_path.exists()
|
|
157
157
|
|
|
158
158
|
# Load and verify
|
|
159
|
-
with open(self.manager.lockfile_path
|
|
159
|
+
with open(self.manager.lockfile_path) as f:
|
|
160
160
|
lockfile = json.load(f)
|
|
161
161
|
|
|
162
162
|
assert "test_cmd" in lockfile["commands"]
|
|
@@ -241,7 +241,7 @@ class TestCustomCommandManager:
|
|
|
241
241
|
assert export_path.exists()
|
|
242
242
|
|
|
243
243
|
# Verify exported data
|
|
244
|
-
with open(export_path
|
|
244
|
+
with open(export_path) as f:
|
|
245
245
|
exported = json.load(f)
|
|
246
246
|
|
|
247
247
|
assert len(exported) == 2
|
|
@@ -293,7 +293,7 @@ class TestCustomCommandManager:
|
|
|
293
293
|
assert results["existing_cmd"] is False
|
|
294
294
|
|
|
295
295
|
# Verify original code is unchanged
|
|
296
|
-
with open(self.commands_dir / "existing_cmd.json"
|
|
296
|
+
with open(self.commands_dir / "existing_cmd.json") as f:
|
|
297
297
|
data = json.load(f)
|
|
298
298
|
assert data["code"] == "original"
|
|
299
299
|
|
|
@@ -322,7 +322,7 @@ class TestCustomCommandManager:
|
|
|
322
322
|
assert results["existing_cmd"] is True
|
|
323
323
|
|
|
324
324
|
# Verify code is updated
|
|
325
|
-
with open(self.commands_dir / "existing_cmd.json"
|
|
325
|
+
with open(self.commands_dir / "existing_cmd.json") as f:
|
|
326
326
|
data = json.load(f)
|
|
327
327
|
assert data["code"] == "new code"
|
|
328
328
|
|