mcli-framework 8.0.38__tar.gz → 8.0.40__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.38 → mcli_framework-8.0.40}/PKG-INFO +1 -1
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/pyproject.toml +1 -1
- mcli_framework-8.0.40/src/mcli/app/import_cmd.py +602 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/init_cmd.py +6 -4
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/main.py +10 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/sync_cmd.py +6 -28
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/constants/__init__.py +8 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/constants/defaults.py +67 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/constants/env.py +3 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/constants/messages.py +106 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/constants/paths.py +3 -1
- mcli_framework-8.0.40/src/mcli/lib/ipfs_utils.py +147 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/paths.py +48 -20
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/workspace_registry.py +29 -23
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/env_cmd.py +11 -2
- mcli_framework-8.0.40/src/mcli/self/ipfs_cmd.py +348 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/migrate_cmd.py +57 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/self_cmd.py +8 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli_framework.egg-info/PKG-INFO +1 -1
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli_framework.egg-info/SOURCES.txt +6 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_all_commands_comprehensive.py +2 -2
- mcli_framework-8.0.40/tests/unit/test_import_cmd.py +866 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_init_mv_cmd.py +16 -16
- mcli_framework-8.0.40/tests/unit/test_ipfs_cmd.py +320 -0
- mcli_framework-8.0.40/tests/unit/test_migrate_rename_dir.py +104 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_paths.py +105 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_workflow_file_completion.py +5 -5
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/dependabot.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/dependency-review-config.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/workflows/build.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/workflows/ci.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/workflows/codeql.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/workflows/docs-links.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/workflows/publish-self-hosted.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/workflows/publish.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/workflows/release.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/workflows/security.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/.github/workflows/test.yml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/LICENSE +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/MANIFEST.in +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/README.md +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/llms-full.txt +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/llms.txt +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/mcli_rust/Cargo.toml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/mcli_rust/src/command_parser.rs +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/mcli_rust/src/file_watcher.rs +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/mcli_rust/src/lib.rs +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/mcli_rust/src/process_manager.rs +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/mcli_rust/src/tfidf.rs +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/setup.cfg +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/commands_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/completion_helpers.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/context_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/create_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/delete_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/edit_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/list_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/migrate_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/model/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/model/model.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/model_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/mv_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/new_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/remove_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/rm_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/search_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/services_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/video/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/app/video/video.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/config.toml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/api/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/api/api.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/api/daemon_client.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/api/daemon_client_local.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/api/daemon_decorator.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/api/mcli_decorators.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/auth.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/aws_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/azure_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/credential_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/gcp_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/key_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/mcli_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/token_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/auth/token_util.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/config/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/config/config.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/constants/commands.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/constants/scripts.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/constants/storage.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/custom_commands.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/discovery/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/discovery/command_discovery.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/erd/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/erd/erd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/erd/generate_graph.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/errors.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/feature_detection.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/files/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/files/files.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/folder_workflows.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/fs/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/fs/fs.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/ipfs_sync.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/lib.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/logger/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/logger/correlation.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/logger/logger.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/logger/structured.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/optional_deps.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/performance/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/performance/optimizer.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/performance/rust_bridge.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/performance/uvloop_config.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/pickles/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/pickles/pickles.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/pyenv/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/pyenv/deps.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/pyenv/manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/pyenv/venv.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/script_loader.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/script_sync.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/script_watcher.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/search/cached_vectorizer.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/secrets/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/secrets/commands.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/secrets/manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/secrets/repl.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/secrets/store.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/config.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/data_pipeline.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/health.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/lsh_client.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/redis_service.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/registry.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/state.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/services/supervisor.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/shell/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/shell/exceptions.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/shell/shell.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/templates/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/templates/command_templates.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/toml/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/toml/toml.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/types.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/ui/styling.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/ui/visual_effects.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/watcher/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/watcher/watcher.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/lib/workflow_models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/app.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/middleware.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/admin_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/auth_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/backtest_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/data_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/model_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/monitoring_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/portfolio_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/prediction_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/trade_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/routers/websocket_router.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/api/schemas.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/auth/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/auth/auth_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/auth/models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/auth/permissions.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/backtesting/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/backtesting/backtest_engine.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/backtesting/performance_metrics.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/backtesting/run.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/cache.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/cli/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/cli/main.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/config/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/config/settings.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/configs/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/configs/dvc_config.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/configs/mlflow_config.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/configs/mlops_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/app.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/app_integrated.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/app_supabase.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/app_training.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/cli.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/common.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/components/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/components/charts.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/components/metrics.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/components/tables.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/overview.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/cicd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/debug_dependencies.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/gravity_viz.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/monte_carlo_predictions.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/predictions_enhanced.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/scrapers_and_logs.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/test_portfolio.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/trading.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/pages/workflows.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/streamlit_extras_utils.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/styles.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/utils.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/dashboard/warning_suppression.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/data_ingestion/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/data_ingestion/api_connectors.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/data_ingestion/data_pipeline.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/data_ingestion/stream_processor.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/database/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/database/migrations/env.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/database/models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/database/session.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/experimentation/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/experimentation/ab_testing.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/features/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/features/ensemble_features.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/features/recommendation_engine.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/features/stock_features.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/features/test_feature_engineering.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/logging.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/mlops/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/mlops/data_versioning.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/mlops/experiment_tracker.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/mlops/model_serving.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/mlops/pipeline_orchestrator.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/models/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/models/base_models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/models/ensemble_models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/models/recommendation_models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/models/test_models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/monitoring/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/monitoring/drift_detection.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/monitoring/metrics.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/optimization/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/optimization/optimize.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/optimization/portfolio_optimizer.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/predictions/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/predictions/monte_carlo.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/predictions/prediction_engine.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/preprocessing/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/preprocessing/data_cleaners.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/preprocessing/feature_extractors.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/preprocessing/ml_pipeline.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/preprocessing/test_preprocessing.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/scripts/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/scripts/populate_sample_data.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/serving/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/serving/serve.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/tasks.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/tests/test_integration.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/tests/test_training_dashboard.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/trading/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/trading/alpaca_client.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/trading/migrations.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/trading/models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/trading/paper_trading.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/trading/risk_management.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/trading/trading_service.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/training/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/training/train.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/ml/training/train_model.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/mygroup/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/mygroup/test_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/public/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/public/commands/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/public/oi/oi.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/public/public.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/completion_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/health_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/logs_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/store_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/test_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/self/workflows_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/storage/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/storage/backends/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/storage/backends/ipfs_backend.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/storage/base.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/storage/cache.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/storage/encryption.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/storage/factory.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/storage/registry.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/storage/storacha_cli.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/async_command_database.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/async_process_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/client.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/daemon.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/daemon_api.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/enhanced_daemon.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/process_cli.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/process_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/daemon/test_daemon.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/dashboard/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/dashboard/dashboard_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/doc_convert.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/docker/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/docker/docker.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/file/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/gcloud/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/gcloud/config.toml +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/gcloud/gcloud.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/git_commit/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/git_commit/ai_service.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/interview/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/lsh_integration.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/client.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/download_and_run_efficient_models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/lightweight_embedder.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/lightweight_model_server.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/lightweight_test.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/model_service.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/ollama_efficient_runner.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/openai_adapter.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/pdf_processor.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/test_efficient_runner.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/test_example.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/test_integration.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/model_service/test_new_features.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/notebook/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/notebook/command_loader.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/notebook/converter.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/notebook/executor.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/notebook/notebook_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/notebook/schema.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/notebook/validator.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/openai/openai.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/registry/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/registry/registry.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/repo/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/repo/repo.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/scheduler/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/scheduler/cron_parser.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/scheduler/job.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/scheduler/models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/scheduler/monitor.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/scheduler/persistence.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/scheduler/scheduler.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/scheduler/validation.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/search/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/secrets/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/secrets/secrets_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/storage/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/storage/storage_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/sync/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/sync/test_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/videos/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/wakatime/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/wakatime/wakatime.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli/workflow/workflow.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli_framework.egg-info/dependency_links.txt +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli_framework.egg-info/entry_points.txt +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli_framework.egg-info/requires.txt +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/src/mcli_framework.egg-info/top_level.txt +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_all_commands.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_app_logs_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_app_redis_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_logs_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_main_app.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_model_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_self_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_self_cmd_plugins.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_self_cmd_utilities.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_workflow_creation_commands.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_workflow_file.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_workflow_gcloud.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/cli/test_workflow_registry.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/conftest.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/e2e/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/e2e/test_complete_workflows.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/e2e/test_model_workflow.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/e2e/test_new_user_workflow.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/e2e/test_update_workflow.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/fixtures/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/fixtures/chat_fixtures.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/fixtures/cli_fixtures.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/fixtures/command_fixtures.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/fixtures/data_fixtures.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/fixtures/db_fixtures.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/fixtures/model_fixtures.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_daemon_server.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_direct_file_execution.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_e2e_dashboard_lsh_supabase.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_flask_webapp.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_folder_workflows_integration.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_gcloud_services.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_ml_auth.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_ml_data_pipeline.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_ml_models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_ml_pipeline.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_module_imports.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_notebook_workflows.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_oi_service.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_repo_operations.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_scheduler_integration.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_service_registry.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_supabase_live_connection.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_video_processing.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_wakatime_api.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_webapp_full.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_workflow.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/integration/test_workflow_commands.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/performance/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/property/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/storage/__init__.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/storage/test_cache.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/storage/test_encryption.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/storage/test_storacha_cli.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_api_utils.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_async_process_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_auth_modules.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_bug_fixes.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_command_fixtures.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_config.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_correlation_logging.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_custom_commands.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_custom_commands_filtering.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_daemon_api.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_dashboard_components.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_dashboard_functions.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_dashboard_pages.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_dependencies.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_doc_convert_workflow.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_emulator_workflow.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_erd_generation.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_erd_generic.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_erd_imports.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_folder_workflows.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_git_commit_workflow.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_health_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_ipfs_retry.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_language_suffix.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_lib_auth.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_lib_files.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_lib_utils.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_logger.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_ml_preprocessing.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_new_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_notebook_command_loader.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_notebook_executor.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_optional_deps.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_pdf_compress.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_prediction_engine.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_pyenv.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_regression.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_scheduler.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_scheduler_cron_parser.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_scheduler_job.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_scheduler_models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_scheduler_monitor.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_scheduler_persistence.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_scheduler_validation.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_script_loader_options.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_security_command_injection.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_self_update.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_service_config.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_service_health.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_service_manager.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_service_state.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_services_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_shell_exceptions.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_shell_functions.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_shell_security.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_store_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_supabase_connection.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_supabase_pagination.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_sync_cmd.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_toml_utils.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_trading_imports.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_ui_rich.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_uv_compat.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/tests/unit/test_workflow_models.py +0 -0
- {mcli_framework-8.0.38 → mcli_framework-8.0.40}/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.40
|
|
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.40"
|
|
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"
|
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Top-level import command for MCLI.
|
|
3
|
+
|
|
4
|
+
This module provides the ``mcli import`` command for importing external scripts
|
|
5
|
+
into the mcli workflow ecosystem. It handles single files, directories,
|
|
6
|
+
native-language detection, wrapper generation for unsupported languages,
|
|
7
|
+
binary rejection, and batch operations with a Rich summary table.
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
mcli import ./scripts/backup.py
|
|
11
|
+
mcli import ./scripts/ --recursive --dry-run
|
|
12
|
+
mcli import ./tool.rb --wrap --global
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import shutil
|
|
17
|
+
import stat
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Dict, List, Optional, Tuple
|
|
20
|
+
|
|
21
|
+
import click
|
|
22
|
+
from rich.table import Table
|
|
23
|
+
|
|
24
|
+
from mcli.app.new_cmd import (
|
|
25
|
+
detect_language_from_file,
|
|
26
|
+
restructure_file_as_command,
|
|
27
|
+
save_script,
|
|
28
|
+
validate_command_name,
|
|
29
|
+
)
|
|
30
|
+
from mcli.lib.constants import (
|
|
31
|
+
ImportDefaults,
|
|
32
|
+
ImportMessages,
|
|
33
|
+
ScriptExtensions,
|
|
34
|
+
ScriptLanguages,
|
|
35
|
+
ScriptMetadataDefaults,
|
|
36
|
+
)
|
|
37
|
+
from mcli.lib.errors import InvalidCommandNameError, UnsupportedFileTypeError
|
|
38
|
+
from mcli.lib.logger.logger import get_logger
|
|
39
|
+
from mcli.lib.paths import get_custom_commands_dir
|
|
40
|
+
from mcli.lib.script_loader import ScriptLoader
|
|
41
|
+
from mcli.lib.ui.styling import console
|
|
42
|
+
|
|
43
|
+
logger = get_logger(__name__)
|
|
44
|
+
|
|
45
|
+
# Exit codes
|
|
46
|
+
EXIT_SUCCESS = 0
|
|
47
|
+
EXIT_ERROR = 1
|
|
48
|
+
|
|
49
|
+
# Result status constants
|
|
50
|
+
STATUS_IMPORTED = "imported"
|
|
51
|
+
STATUS_WRAPPED = "wrapped"
|
|
52
|
+
STATUS_LINKED = "linked"
|
|
53
|
+
STATUS_MOVED = "moved"
|
|
54
|
+
STATUS_SKIPPED = "skipped"
|
|
55
|
+
STATUS_DRY_RUN = "dry-run"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# =============================================================================
|
|
59
|
+
# Detection helpers
|
|
60
|
+
# =============================================================================
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _is_binary(file_path: Path) -> bool:
|
|
64
|
+
"""Return True if *file_path* looks like a binary file.
|
|
65
|
+
|
|
66
|
+
Reads the first ``ImportDefaults.BINARY_CHECK_SIZE`` bytes and checks for
|
|
67
|
+
null bytes. ``.ipynb`` files are exempt (they are JSON).
|
|
68
|
+
"""
|
|
69
|
+
if file_path.suffix.lower() == ScriptExtensions.IPYNB:
|
|
70
|
+
return False
|
|
71
|
+
try:
|
|
72
|
+
with open(file_path, "rb") as fh:
|
|
73
|
+
chunk = fh.read(ImportDefaults.BINARY_CHECK_SIZE)
|
|
74
|
+
return b"\x00" in chunk
|
|
75
|
+
except OSError:
|
|
76
|
+
return True
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _is_importable(
|
|
80
|
+
file_path: Path,
|
|
81
|
+
) -> Tuple[bool, Optional[str], Optional[bool], Optional[str]]:
|
|
82
|
+
"""Classify a file as importable, wrappable, or rejected.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
``(ok, language_or_None, needs_wrapper, skip_reason_or_None)``
|
|
86
|
+
"""
|
|
87
|
+
name = file_path.name
|
|
88
|
+
|
|
89
|
+
# Hidden files
|
|
90
|
+
if name.startswith("."):
|
|
91
|
+
return (False, None, None, "hidden")
|
|
92
|
+
|
|
93
|
+
# Rejected extensions
|
|
94
|
+
ext_lower = file_path.suffix.lower()
|
|
95
|
+
if ext_lower in ImportDefaults.REJECTED_EXTENSIONS:
|
|
96
|
+
return (False, None, None, "non-script extension")
|
|
97
|
+
|
|
98
|
+
# Size check
|
|
99
|
+
try:
|
|
100
|
+
size = file_path.stat().st_size
|
|
101
|
+
except OSError:
|
|
102
|
+
return (False, None, None, "permission denied")
|
|
103
|
+
if size > ImportDefaults.MAX_FILE_SIZE:
|
|
104
|
+
return (False, None, None, "too large")
|
|
105
|
+
|
|
106
|
+
# Binary check
|
|
107
|
+
if _is_binary(file_path):
|
|
108
|
+
return (False, None, None, "binary")
|
|
109
|
+
|
|
110
|
+
# Try native language detection first
|
|
111
|
+
try:
|
|
112
|
+
lang = detect_language_from_file(file_path)
|
|
113
|
+
return (True, lang, False, None)
|
|
114
|
+
except UnsupportedFileTypeError:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
# Check wrapper interpreters (by extension)
|
|
118
|
+
ext_raw = file_path.suffix # preserve case for .R
|
|
119
|
+
interpreter = ImportDefaults.WRAPPER_INTERPRETERS.get(ext_raw)
|
|
120
|
+
if interpreter is None:
|
|
121
|
+
interpreter = ImportDefaults.WRAPPER_INTERPRETERS.get(ext_lower)
|
|
122
|
+
if interpreter:
|
|
123
|
+
return (True, None, True, None)
|
|
124
|
+
|
|
125
|
+
# Check for shebang
|
|
126
|
+
try:
|
|
127
|
+
with open(file_path, "r", encoding="utf-8", errors="ignore") as fh:
|
|
128
|
+
first_line = fh.readline(256)
|
|
129
|
+
if first_line.startswith("#!"):
|
|
130
|
+
return (True, None, True, None)
|
|
131
|
+
except OSError:
|
|
132
|
+
return (False, None, None, "permission denied")
|
|
133
|
+
|
|
134
|
+
# Check if executable (and has no extension)
|
|
135
|
+
if not file_path.suffix:
|
|
136
|
+
try:
|
|
137
|
+
if os.access(file_path, os.X_OK):
|
|
138
|
+
return (True, None, True, None)
|
|
139
|
+
except OSError:
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
return (False, None, None, "no shebang or known extension")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _detect_wrapper_interpreter(file_path: Path) -> str:
|
|
146
|
+
"""Return the interpreter string for a non-native script.
|
|
147
|
+
|
|
148
|
+
Falls back to reading the shebang line.
|
|
149
|
+
"""
|
|
150
|
+
ext_raw = file_path.suffix
|
|
151
|
+
ext_lower = ext_raw.lower()
|
|
152
|
+
interpreter = ImportDefaults.WRAPPER_INTERPRETERS.get(ext_raw)
|
|
153
|
+
if interpreter is None:
|
|
154
|
+
interpreter = ImportDefaults.WRAPPER_INTERPRETERS.get(ext_lower)
|
|
155
|
+
if interpreter:
|
|
156
|
+
return interpreter
|
|
157
|
+
|
|
158
|
+
# Try shebang
|
|
159
|
+
try:
|
|
160
|
+
with open(file_path, "r", encoding="utf-8", errors="ignore") as fh:
|
|
161
|
+
first_line = fh.readline(256).strip()
|
|
162
|
+
if first_line.startswith("#!"):
|
|
163
|
+
# e.g. #!/usr/bin/env ruby -> ruby
|
|
164
|
+
parts = first_line.lstrip("#!").strip().split()
|
|
165
|
+
if parts:
|
|
166
|
+
interp = parts[-1] # last token after env
|
|
167
|
+
return interp
|
|
168
|
+
except OSError:
|
|
169
|
+
pass
|
|
170
|
+
|
|
171
|
+
return "bash"
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# =============================================================================
|
|
175
|
+
# Wrapper generation
|
|
176
|
+
# =============================================================================
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _create_wrapper_script(
|
|
180
|
+
original_path: Path,
|
|
181
|
+
command_name: str,
|
|
182
|
+
interpreter: str,
|
|
183
|
+
group: str,
|
|
184
|
+
) -> str:
|
|
185
|
+
"""Generate a shell wrapper script that delegates to *original_path*."""
|
|
186
|
+
return (
|
|
187
|
+
f"#!/usr/bin/env bash\n"
|
|
188
|
+
f"# @description: Wrapper for {original_path.name}\n"
|
|
189
|
+
f"# @version: {ScriptMetadataDefaults.VERSION}\n"
|
|
190
|
+
f"# @group: {group}\n"
|
|
191
|
+
f'\nexec {interpreter} "{original_path}" "$@"\n'
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# =============================================================================
|
|
196
|
+
# Name derivation
|
|
197
|
+
# =============================================================================
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _derive_command_name(file_path: Path) -> str:
|
|
201
|
+
"""Derive a valid mcli command name from a filename stem."""
|
|
202
|
+
stem = file_path.stem.lower().replace("-", "_")
|
|
203
|
+
try:
|
|
204
|
+
return validate_command_name(stem)
|
|
205
|
+
except InvalidCommandNameError:
|
|
206
|
+
# Prefix with 'cmd_' if it starts with a digit or is otherwise invalid
|
|
207
|
+
prefixed = f"cmd_{stem}"
|
|
208
|
+
return validate_command_name(prefixed)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _resolve_name_conflicts(
|
|
212
|
+
files: List[Tuple[Path, str, bool]],
|
|
213
|
+
) -> List[Tuple[Path, str, bool, str]]:
|
|
214
|
+
"""Resolve duplicate command names for directory imports.
|
|
215
|
+
|
|
216
|
+
For conflicts, prefix with parent directory name:
|
|
217
|
+
``db/backup.sh`` becomes ``db_backup``.
|
|
218
|
+
|
|
219
|
+
Returns list of ``(path, language_or_None, needs_wrapper, command_name)``.
|
|
220
|
+
"""
|
|
221
|
+
# First pass: derive names
|
|
222
|
+
entries: List[Tuple[Path, str, bool, str]] = []
|
|
223
|
+
for fpath, lang, wrap in files:
|
|
224
|
+
entries.append((fpath, lang, wrap, _derive_command_name(fpath)))
|
|
225
|
+
|
|
226
|
+
# Find duplicates
|
|
227
|
+
name_counts: Dict[str, int] = {}
|
|
228
|
+
for _, _, _, cname in entries:
|
|
229
|
+
name_counts[cname] = name_counts.get(cname, 0) + 1
|
|
230
|
+
|
|
231
|
+
# Resolve duplicates
|
|
232
|
+
resolved: List[Tuple[Path, str, bool, str]] = []
|
|
233
|
+
for fpath, lang, wrap, cname in entries:
|
|
234
|
+
if name_counts[cname] > 1:
|
|
235
|
+
parent = fpath.parent.name.lower().replace("-", "_")
|
|
236
|
+
if parent:
|
|
237
|
+
new_name = f"{parent}_{cname}"
|
|
238
|
+
try:
|
|
239
|
+
new_name = validate_command_name(new_name)
|
|
240
|
+
except InvalidCommandNameError:
|
|
241
|
+
new_name = cname # fall back
|
|
242
|
+
resolved.append((fpath, lang, wrap, new_name))
|
|
243
|
+
else:
|
|
244
|
+
resolved.append((fpath, lang, wrap, cname))
|
|
245
|
+
else:
|
|
246
|
+
resolved.append((fpath, lang, wrap, cname))
|
|
247
|
+
|
|
248
|
+
return resolved
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
# =============================================================================
|
|
252
|
+
# Scanning
|
|
253
|
+
# =============================================================================
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _scan_source(
|
|
257
|
+
source: Path,
|
|
258
|
+
recursive: bool,
|
|
259
|
+
) -> List[Tuple[Path, Optional[str], bool]]:
|
|
260
|
+
"""Scan *source* and return importable files.
|
|
261
|
+
|
|
262
|
+
Returns list of ``(path, language_or_None, needs_wrapper)``.
|
|
263
|
+
Skipped files are logged but not returned.
|
|
264
|
+
"""
|
|
265
|
+
candidates: List[Tuple[Path, Optional[str], bool]] = []
|
|
266
|
+
|
|
267
|
+
if source.is_file():
|
|
268
|
+
ok, lang, wrap, reason = _is_importable(source)
|
|
269
|
+
if ok:
|
|
270
|
+
candidates.append((source, lang, wrap or False))
|
|
271
|
+
else:
|
|
272
|
+
logger.info("Skipped %s: %s", source, reason)
|
|
273
|
+
return candidates
|
|
274
|
+
|
|
275
|
+
# Directory
|
|
276
|
+
iterator = source.rglob("*") if recursive else source.iterdir()
|
|
277
|
+
for entry in sorted(iterator):
|
|
278
|
+
if not entry.is_file():
|
|
279
|
+
continue
|
|
280
|
+
ok, lang, wrap, reason = _is_importable(entry)
|
|
281
|
+
if ok:
|
|
282
|
+
candidates.append((entry, lang, wrap or False))
|
|
283
|
+
else:
|
|
284
|
+
logger.info("Skipped %s: %s", entry, reason)
|
|
285
|
+
|
|
286
|
+
return candidates
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
# =============================================================================
|
|
290
|
+
# File transfer
|
|
291
|
+
# =============================================================================
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _perform_transfer(
|
|
295
|
+
src: Path,
|
|
296
|
+
dst: Path,
|
|
297
|
+
*,
|
|
298
|
+
link: bool = False,
|
|
299
|
+
move: bool = False,
|
|
300
|
+
) -> None:
|
|
301
|
+
"""Copy, symlink, or move *src* to *dst*."""
|
|
302
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
303
|
+
if link:
|
|
304
|
+
dst.symlink_to(src.resolve())
|
|
305
|
+
elif move:
|
|
306
|
+
shutil.move(str(src), str(dst))
|
|
307
|
+
else:
|
|
308
|
+
shutil.copy2(str(src), str(dst))
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
# =============================================================================
|
|
312
|
+
# Single-file import
|
|
313
|
+
# =============================================================================
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def _import_single_file(
|
|
317
|
+
file_path: Path,
|
|
318
|
+
command_name: str,
|
|
319
|
+
language: Optional[str],
|
|
320
|
+
needs_wrapper: bool,
|
|
321
|
+
workflows_dir: Path,
|
|
322
|
+
group: str,
|
|
323
|
+
version: str,
|
|
324
|
+
*,
|
|
325
|
+
link: bool = False,
|
|
326
|
+
move: bool = False,
|
|
327
|
+
force: bool = False,
|
|
328
|
+
wrap: bool = True,
|
|
329
|
+
dry_run: bool = False,
|
|
330
|
+
) -> Tuple[str, str, str]:
|
|
331
|
+
"""Import a single file into the workflows directory.
|
|
332
|
+
|
|
333
|
+
Returns ``(command_name, action_label, status)``.
|
|
334
|
+
"""
|
|
335
|
+
# Check for existing command
|
|
336
|
+
if language:
|
|
337
|
+
ext = ScriptExtensions.BY_LANGUAGE.get(language, ".sh")
|
|
338
|
+
else:
|
|
339
|
+
ext = ".sh" # wrappers are always shell
|
|
340
|
+
target = workflows_dir / f"{command_name}{ext}"
|
|
341
|
+
|
|
342
|
+
if target.exists() and not force:
|
|
343
|
+
return (command_name, "skip", STATUS_SKIPPED)
|
|
344
|
+
|
|
345
|
+
if dry_run:
|
|
346
|
+
action = (
|
|
347
|
+
"wrap"
|
|
348
|
+
if (needs_wrapper and wrap)
|
|
349
|
+
else ("link" if link else ("move" if move else "copy"))
|
|
350
|
+
)
|
|
351
|
+
return (command_name, action, STATUS_DRY_RUN)
|
|
352
|
+
|
|
353
|
+
# ---- Wrapper path ----
|
|
354
|
+
if needs_wrapper and wrap:
|
|
355
|
+
interpreter = _detect_wrapper_interpreter(file_path)
|
|
356
|
+
wrapper_code = _create_wrapper_script(
|
|
357
|
+
original_path=file_path.resolve(),
|
|
358
|
+
command_name=command_name,
|
|
359
|
+
interpreter=interpreter,
|
|
360
|
+
group=group,
|
|
361
|
+
)
|
|
362
|
+
target = workflows_dir / f"{command_name}.sh"
|
|
363
|
+
if target.exists() and not force:
|
|
364
|
+
return (command_name, "skip", STATUS_SKIPPED)
|
|
365
|
+
workflows_dir.mkdir(parents=True, exist_ok=True)
|
|
366
|
+
target.write_text(wrapper_code)
|
|
367
|
+
target.chmod(target.stat().st_mode | stat.S_IXUSR)
|
|
368
|
+
return (command_name, "wrap", STATUS_WRAPPED)
|
|
369
|
+
|
|
370
|
+
# ---- Native import (copy / link / move) ----
|
|
371
|
+
if link:
|
|
372
|
+
_perform_transfer(file_path, target, link=True)
|
|
373
|
+
return (command_name, "link", STATUS_LINKED)
|
|
374
|
+
|
|
375
|
+
if move:
|
|
376
|
+
# Read content before moving for metadata injection
|
|
377
|
+
code = restructure_file_as_command(
|
|
378
|
+
file_path=file_path,
|
|
379
|
+
name=command_name,
|
|
380
|
+
description=f"{command_name.replace('_', ' ').title()} command",
|
|
381
|
+
group=group,
|
|
382
|
+
version=version,
|
|
383
|
+
language=language,
|
|
384
|
+
)
|
|
385
|
+
saved = save_script(workflows_dir, command_name, code, language)
|
|
386
|
+
# Remove original after successful save
|
|
387
|
+
file_path.unlink()
|
|
388
|
+
return (command_name, "move", STATUS_MOVED)
|
|
389
|
+
|
|
390
|
+
# Default: copy with metadata injection
|
|
391
|
+
code = restructure_file_as_command(
|
|
392
|
+
file_path=file_path,
|
|
393
|
+
name=command_name,
|
|
394
|
+
description=f"{command_name.replace('_', ' ').title()} command",
|
|
395
|
+
group=group,
|
|
396
|
+
version=version,
|
|
397
|
+
language=language,
|
|
398
|
+
)
|
|
399
|
+
save_script(workflows_dir, command_name, code, language)
|
|
400
|
+
return (command_name, "copy", STATUS_IMPORTED)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
# =============================================================================
|
|
404
|
+
# Summary display
|
|
405
|
+
# =============================================================================
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def _display_summary(results: List[Tuple[str, str, str]], verbose: bool) -> None:
|
|
409
|
+
"""Show a Rich table summarising the import results."""
|
|
410
|
+
if not results:
|
|
411
|
+
return
|
|
412
|
+
|
|
413
|
+
table = Table(title=ImportMessages.SUMMARY_HEADER, show_lines=False)
|
|
414
|
+
table.add_column(ImportMessages.COL_NAME, style="cyan")
|
|
415
|
+
table.add_column(ImportMessages.COL_ACTION)
|
|
416
|
+
table.add_column(ImportMessages.COL_STATUS)
|
|
417
|
+
|
|
418
|
+
status_styles = {
|
|
419
|
+
STATUS_IMPORTED: "green",
|
|
420
|
+
STATUS_WRAPPED: "green",
|
|
421
|
+
STATUS_LINKED: "green",
|
|
422
|
+
STATUS_MOVED: "green",
|
|
423
|
+
STATUS_SKIPPED: "yellow",
|
|
424
|
+
STATUS_DRY_RUN: "dim",
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
for name, action, rstatus in results:
|
|
428
|
+
style = status_styles.get(rstatus, "white")
|
|
429
|
+
table.add_row(name, action, f"[{style}]{rstatus}[/{style}]")
|
|
430
|
+
|
|
431
|
+
console.print(table)
|
|
432
|
+
|
|
433
|
+
# Counters
|
|
434
|
+
imported = sum(
|
|
435
|
+
1
|
|
436
|
+
for _, _, s in results
|
|
437
|
+
if s in (STATUS_IMPORTED, STATUS_WRAPPED, STATUS_LINKED, STATUS_MOVED)
|
|
438
|
+
)
|
|
439
|
+
skipped = sum(1 for _, _, s in results if s == STATUS_SKIPPED)
|
|
440
|
+
if imported:
|
|
441
|
+
console.print(f"[green]{imported} imported[/green]", end="")
|
|
442
|
+
if skipped:
|
|
443
|
+
sep = ", " if imported else ""
|
|
444
|
+
console.print(f"{sep}[yellow]{skipped} skipped[/yellow]", end="")
|
|
445
|
+
console.print()
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
# =============================================================================
|
|
449
|
+
# Click command
|
|
450
|
+
# =============================================================================
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
@click.command("import")
|
|
454
|
+
@click.argument(
|
|
455
|
+
"source",
|
|
456
|
+
type=click.Path(exists=True, resolve_path=True),
|
|
457
|
+
)
|
|
458
|
+
@click.option(
|
|
459
|
+
"--global",
|
|
460
|
+
"-g",
|
|
461
|
+
"is_global",
|
|
462
|
+
is_flag=True,
|
|
463
|
+
default=False,
|
|
464
|
+
help="Import to global workflows (~/.mcli/workflows/)",
|
|
465
|
+
)
|
|
466
|
+
@click.option(
|
|
467
|
+
"--group",
|
|
468
|
+
default=ImportDefaults.DEFAULT_GROUP,
|
|
469
|
+
help=f"Metadata group for imported scripts (default: '{ImportDefaults.DEFAULT_GROUP}')",
|
|
470
|
+
)
|
|
471
|
+
@click.option(
|
|
472
|
+
"--dry-run",
|
|
473
|
+
"-n",
|
|
474
|
+
is_flag=True,
|
|
475
|
+
default=False,
|
|
476
|
+
help="Preview what would be imported without making changes",
|
|
477
|
+
)
|
|
478
|
+
@click.option(
|
|
479
|
+
"--link",
|
|
480
|
+
is_flag=True,
|
|
481
|
+
default=False,
|
|
482
|
+
help="Symlink instead of copy",
|
|
483
|
+
)
|
|
484
|
+
@click.option(
|
|
485
|
+
"--move",
|
|
486
|
+
is_flag=True,
|
|
487
|
+
default=False,
|
|
488
|
+
help="Move source files (mutually exclusive with --link)",
|
|
489
|
+
)
|
|
490
|
+
@click.option(
|
|
491
|
+
"--force",
|
|
492
|
+
"-f",
|
|
493
|
+
is_flag=True,
|
|
494
|
+
default=False,
|
|
495
|
+
help="Overwrite existing commands",
|
|
496
|
+
)
|
|
497
|
+
@click.option(
|
|
498
|
+
"--recursive",
|
|
499
|
+
"-r",
|
|
500
|
+
is_flag=True,
|
|
501
|
+
default=False,
|
|
502
|
+
help="Recurse into subdirectories",
|
|
503
|
+
)
|
|
504
|
+
@click.option(
|
|
505
|
+
"--wrap/--no-wrap",
|
|
506
|
+
default=True,
|
|
507
|
+
help="Create shell wrappers for unsupported languages (default: wrap)",
|
|
508
|
+
)
|
|
509
|
+
@click.option(
|
|
510
|
+
"--verbose",
|
|
511
|
+
"-v",
|
|
512
|
+
is_flag=True,
|
|
513
|
+
default=False,
|
|
514
|
+
help="Show detailed per-file output",
|
|
515
|
+
)
|
|
516
|
+
def import_cmd(
|
|
517
|
+
source: str,
|
|
518
|
+
is_global: bool,
|
|
519
|
+
group: str,
|
|
520
|
+
dry_run: bool,
|
|
521
|
+
link: bool,
|
|
522
|
+
move: bool,
|
|
523
|
+
force: bool,
|
|
524
|
+
recursive: bool,
|
|
525
|
+
wrap: bool,
|
|
526
|
+
verbose: bool,
|
|
527
|
+
) -> int:
|
|
528
|
+
"""📥 Import external scripts into the mcli workflow ecosystem.
|
|
529
|
+
|
|
530
|
+
SOURCE can be a single file or a directory. Native scripts (.py, .sh, .js,
|
|
531
|
+
.ts, .ipynb) are copied with metadata injected. Unsupported languages
|
|
532
|
+
(Ruby, Perl, Go, etc.) get a thin shell wrapper that delegates to the
|
|
533
|
+
original.
|
|
534
|
+
|
|
535
|
+
\b
|
|
536
|
+
Examples:
|
|
537
|
+
mcli import ./backup.py
|
|
538
|
+
mcli import ./scripts/ --recursive --dry-run
|
|
539
|
+
mcli import ./tool.rb --wrap --global
|
|
540
|
+
mcli import ./deploy.sh --link
|
|
541
|
+
"""
|
|
542
|
+
if link and move:
|
|
543
|
+
raise click.UsageError("--link and --move are mutually exclusive")
|
|
544
|
+
|
|
545
|
+
source_path = Path(source)
|
|
546
|
+
workflows_dir = get_custom_commands_dir(global_mode=is_global)
|
|
547
|
+
version = ScriptMetadataDefaults.VERSION
|
|
548
|
+
|
|
549
|
+
if dry_run:
|
|
550
|
+
console.print(ImportMessages.DRY_RUN_HEADER)
|
|
551
|
+
|
|
552
|
+
# Move confirmation (unless force or dry-run)
|
|
553
|
+
if move and not force and not dry_run:
|
|
554
|
+
if not click.confirm(ImportMessages.MOVE_CONFIRM):
|
|
555
|
+
click.echo("Cancelled.")
|
|
556
|
+
return EXIT_SUCCESS
|
|
557
|
+
|
|
558
|
+
# Scan
|
|
559
|
+
candidates = _scan_source(source_path, recursive)
|
|
560
|
+
|
|
561
|
+
if not candidates:
|
|
562
|
+
console.print(ImportMessages.NO_IMPORTABLE.format(path=source_path))
|
|
563
|
+
return EXIT_SUCCESS
|
|
564
|
+
|
|
565
|
+
# Resolve names (directory import may have conflicts)
|
|
566
|
+
named = _resolve_name_conflicts(candidates)
|
|
567
|
+
|
|
568
|
+
# Import each file
|
|
569
|
+
results: List[Tuple[str, str, str]] = []
|
|
570
|
+
for fpath, lang, needs_wrapper, cmd_name in named:
|
|
571
|
+
if verbose and not dry_run:
|
|
572
|
+
console.print(ImportMessages.IMPORTING_FILE.format(path=fpath))
|
|
573
|
+
try:
|
|
574
|
+
result = _import_single_file(
|
|
575
|
+
file_path=fpath,
|
|
576
|
+
command_name=cmd_name,
|
|
577
|
+
language=lang,
|
|
578
|
+
needs_wrapper=needs_wrapper,
|
|
579
|
+
workflows_dir=workflows_dir,
|
|
580
|
+
group=group,
|
|
581
|
+
version=version,
|
|
582
|
+
link=link,
|
|
583
|
+
move=move,
|
|
584
|
+
force=force,
|
|
585
|
+
wrap=wrap,
|
|
586
|
+
dry_run=dry_run,
|
|
587
|
+
)
|
|
588
|
+
results.append(result)
|
|
589
|
+
except Exception as exc:
|
|
590
|
+
logger.warning("Failed to import %s: %s", fpath, exc)
|
|
591
|
+
results.append((cmd_name, "error", STATUS_SKIPPED))
|
|
592
|
+
|
|
593
|
+
# Update lockfile (unless dry-run)
|
|
594
|
+
if not dry_run:
|
|
595
|
+
try:
|
|
596
|
+
loader = ScriptLoader(workflows_dir)
|
|
597
|
+
loader.save_lockfile()
|
|
598
|
+
except Exception as exc:
|
|
599
|
+
logger.warning("Failed to update lockfile: %s", exc)
|
|
600
|
+
|
|
601
|
+
_display_summary(results, verbose)
|
|
602
|
+
return EXIT_SUCCESS
|
|
@@ -30,11 +30,11 @@ def init(is_global, git, force):
|
|
|
30
30
|
"""🚀 Initialize workflows directory structure.
|
|
31
31
|
|
|
32
32
|
Creates the necessary directories and configuration files for managing
|
|
33
|
-
custom workflows. By default, creates a local
|
|
33
|
+
custom workflows. By default, creates a local mcli/workflows/ directory
|
|
34
34
|
in the current directory.
|
|
35
35
|
|
|
36
36
|
Examples:
|
|
37
|
-
mcli init # Initialize local
|
|
37
|
+
mcli init # Initialize local mcli/workflows/ in current directory
|
|
38
38
|
mcli init --global # Initialize global ~/.mcli/workflows/
|
|
39
39
|
mcli init --git # Also initialize git repository
|
|
40
40
|
"""
|
|
@@ -50,11 +50,13 @@ def init(is_global, git, force):
|
|
|
50
50
|
workflows_dir = get_mcli_home() / "workflows"
|
|
51
51
|
is_local = False
|
|
52
52
|
else:
|
|
53
|
-
# Local:
|
|
53
|
+
# Local: mcli/workflows in current directory (default behavior)
|
|
54
54
|
from pathlib import Path
|
|
55
55
|
|
|
56
|
+
from mcli.lib.constants.paths import DirNames
|
|
57
|
+
|
|
56
58
|
cwd = Path.cwd()
|
|
57
|
-
workflows_dir = cwd /
|
|
59
|
+
workflows_dir = cwd / DirNames.LOCAL_MCLI / "workflows"
|
|
58
60
|
is_local = True
|
|
59
61
|
|
|
60
62
|
lockfile_path = workflows_dir / "commands.lock.json"
|
|
@@ -13,6 +13,7 @@ from mcli.lib.logger.logger import disable_runtime_tracing, enable_runtime_traci
|
|
|
13
13
|
COMMAND_ORDER = [
|
|
14
14
|
"init",
|
|
15
15
|
"new",
|
|
16
|
+
"import",
|
|
16
17
|
"edit",
|
|
17
18
|
"mv",
|
|
18
19
|
"rm",
|
|
@@ -395,6 +396,15 @@ def _add_lazy_commands(app: click.Group):
|
|
|
395
396
|
except ImportError as e:
|
|
396
397
|
logger.debug(f"Could not load new command: {e}")
|
|
397
398
|
|
|
399
|
+
# mcli import - Import external scripts
|
|
400
|
+
try:
|
|
401
|
+
from mcli.app.import_cmd import import_cmd
|
|
402
|
+
|
|
403
|
+
app.add_command(import_cmd, name="import")
|
|
404
|
+
logger.debug("Added import command")
|
|
405
|
+
except ImportError as e:
|
|
406
|
+
logger.debug(f"Could not load import command: {e}")
|
|
407
|
+
|
|
398
408
|
# mcli edit - Edit a command
|
|
399
409
|
try:
|
|
400
410
|
from mcli.app.edit_cmd import edit
|