mcli-framework 8.0.38__tar.gz → 8.0.39__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (487) hide show
  1. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/PKG-INFO +1 -1
  2. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/pyproject.toml +1 -1
  3. mcli_framework-8.0.39/src/mcli/app/import_cmd.py +602 -0
  4. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/main.py +10 -0
  5. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/sync_cmd.py +6 -28
  6. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/constants/__init__.py +8 -0
  7. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/constants/defaults.py +67 -0
  8. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/constants/messages.py +102 -0
  9. mcli_framework-8.0.39/src/mcli/lib/ipfs_utils.py +147 -0
  10. mcli_framework-8.0.39/src/mcli/self/ipfs_cmd.py +348 -0
  11. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/self_cmd.py +8 -0
  12. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli_framework.egg-info/PKG-INFO +1 -1
  13. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli_framework.egg-info/SOURCES.txt +5 -0
  14. mcli_framework-8.0.39/tests/unit/test_import_cmd.py +866 -0
  15. mcli_framework-8.0.39/tests/unit/test_ipfs_cmd.py +320 -0
  16. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/dependabot.yml +0 -0
  17. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/dependency-review-config.yml +0 -0
  18. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/workflows/build.yml +0 -0
  19. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/workflows/ci.yml +0 -0
  20. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/workflows/codeql.yml +0 -0
  21. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/workflows/docs-links.yml +0 -0
  22. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/workflows/publish-self-hosted.yml +0 -0
  23. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/workflows/publish.yml +0 -0
  24. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/workflows/release.yml +0 -0
  25. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/workflows/security.yml +0 -0
  26. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/.github/workflows/test.yml +0 -0
  27. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/LICENSE +0 -0
  28. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/MANIFEST.in +0 -0
  29. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/README.md +0 -0
  30. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/llms-full.txt +0 -0
  31. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/llms.txt +0 -0
  32. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/mcli_rust/Cargo.toml +0 -0
  33. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/mcli_rust/src/command_parser.rs +0 -0
  34. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/mcli_rust/src/file_watcher.rs +0 -0
  35. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/mcli_rust/src/lib.rs +0 -0
  36. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/mcli_rust/src/process_manager.rs +0 -0
  37. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/mcli_rust/src/tfidf.rs +0 -0
  38. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/setup.cfg +0 -0
  39. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/__init__.py +0 -0
  40. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/__init__.py +0 -0
  41. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/commands_cmd.py +0 -0
  42. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/completion_helpers.py +0 -0
  43. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/context_cmd.py +0 -0
  44. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/create_cmd.py +0 -0
  45. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/delete_cmd.py +0 -0
  46. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/edit_cmd.py +0 -0
  47. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/init_cmd.py +0 -0
  48. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/list_cmd.py +0 -0
  49. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/migrate_cmd.py +0 -0
  50. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/model/__init__.py +0 -0
  51. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/model/model.py +0 -0
  52. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/model_cmd.py +0 -0
  53. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/mv_cmd.py +0 -0
  54. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/new_cmd.py +0 -0
  55. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/remove_cmd.py +0 -0
  56. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/rm_cmd.py +0 -0
  57. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/search_cmd.py +0 -0
  58. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/services_cmd.py +0 -0
  59. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/video/__init__.py +0 -0
  60. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/app/video/video.py +0 -0
  61. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/config.toml +0 -0
  62. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/__init__.py +0 -0
  63. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/api/__init__.py +0 -0
  64. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/api/api.py +0 -0
  65. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/api/daemon_client.py +0 -0
  66. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/api/daemon_client_local.py +0 -0
  67. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/api/daemon_decorator.py +0 -0
  68. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/api/mcli_decorators.py +0 -0
  69. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/__init__.py +0 -0
  70. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/auth.py +0 -0
  71. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/aws_manager.py +0 -0
  72. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/azure_manager.py +0 -0
  73. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/credential_manager.py +0 -0
  74. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/gcp_manager.py +0 -0
  75. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/key_manager.py +0 -0
  76. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/mcli_manager.py +0 -0
  77. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/token_manager.py +0 -0
  78. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/auth/token_util.py +0 -0
  79. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/config/__init__.py +0 -0
  80. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/config/config.py +0 -0
  81. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/constants/commands.py +0 -0
  82. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/constants/env.py +0 -0
  83. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/constants/paths.py +0 -0
  84. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/constants/scripts.py +0 -0
  85. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/constants/storage.py +0 -0
  86. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/custom_commands.py +0 -0
  87. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/discovery/__init__.py +0 -0
  88. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/discovery/command_discovery.py +0 -0
  89. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/erd/__init__.py +0 -0
  90. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/erd/erd.py +0 -0
  91. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/erd/generate_graph.py +0 -0
  92. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/errors.py +0 -0
  93. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/feature_detection.py +0 -0
  94. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/files/__init__.py +0 -0
  95. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/files/files.py +0 -0
  96. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/folder_workflows.py +0 -0
  97. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/fs/__init__.py +0 -0
  98. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/fs/fs.py +0 -0
  99. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/ipfs_sync.py +0 -0
  100. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/lib.py +0 -0
  101. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/logger/__init__.py +0 -0
  102. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/logger/correlation.py +0 -0
  103. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/logger/logger.py +0 -0
  104. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/logger/structured.py +0 -0
  105. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/optional_deps.py +0 -0
  106. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/paths.py +0 -0
  107. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/performance/__init__.py +0 -0
  108. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/performance/optimizer.py +0 -0
  109. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/performance/rust_bridge.py +0 -0
  110. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/performance/uvloop_config.py +0 -0
  111. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/pickles/__init__.py +0 -0
  112. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/pickles/pickles.py +0 -0
  113. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/pyenv/__init__.py +0 -0
  114. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/pyenv/deps.py +0 -0
  115. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/pyenv/manager.py +0 -0
  116. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/pyenv/venv.py +0 -0
  117. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/script_loader.py +0 -0
  118. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/script_sync.py +0 -0
  119. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/script_watcher.py +0 -0
  120. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/search/cached_vectorizer.py +0 -0
  121. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/secrets/__init__.py +0 -0
  122. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/secrets/commands.py +0 -0
  123. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/secrets/manager.py +0 -0
  124. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/secrets/repl.py +0 -0
  125. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/secrets/store.py +0 -0
  126. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/__init__.py +0 -0
  127. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/config.py +0 -0
  128. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/data_pipeline.py +0 -0
  129. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/health.py +0 -0
  130. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/lsh_client.py +0 -0
  131. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/manager.py +0 -0
  132. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/redis_service.py +0 -0
  133. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/registry.py +0 -0
  134. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/state.py +0 -0
  135. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/services/supervisor.py +0 -0
  136. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/shell/__init__.py +0 -0
  137. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/shell/exceptions.py +0 -0
  138. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/shell/shell.py +0 -0
  139. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/templates/__init__.py +0 -0
  140. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/templates/command_templates.py +0 -0
  141. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/toml/__init__.py +0 -0
  142. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/toml/toml.py +0 -0
  143. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/types.py +0 -0
  144. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/ui/styling.py +0 -0
  145. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/ui/visual_effects.py +0 -0
  146. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/watcher/__init__.py +0 -0
  147. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/watcher/watcher.py +0 -0
  148. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/workflow_models.py +0 -0
  149. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/lib/workspace_registry.py +0 -0
  150. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/__init__.py +0 -0
  151. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/__init__.py +0 -0
  152. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/app.py +0 -0
  153. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/middleware.py +0 -0
  154. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/__init__.py +0 -0
  155. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/admin_router.py +0 -0
  156. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/auth_router.py +0 -0
  157. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/backtest_router.py +0 -0
  158. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/data_router.py +0 -0
  159. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/model_router.py +0 -0
  160. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/monitoring_router.py +0 -0
  161. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/portfolio_router.py +0 -0
  162. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/prediction_router.py +0 -0
  163. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/trade_router.py +0 -0
  164. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/routers/websocket_router.py +0 -0
  165. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/api/schemas.py +0 -0
  166. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/auth/__init__.py +0 -0
  167. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/auth/auth_manager.py +0 -0
  168. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/auth/models.py +0 -0
  169. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/auth/permissions.py +0 -0
  170. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/backtesting/__init__.py +0 -0
  171. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/backtesting/backtest_engine.py +0 -0
  172. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/backtesting/performance_metrics.py +0 -0
  173. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/backtesting/run.py +0 -0
  174. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/cache.py +0 -0
  175. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/cli/__init__.py +0 -0
  176. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/cli/main.py +0 -0
  177. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/config/__init__.py +0 -0
  178. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/config/settings.py +0 -0
  179. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/configs/__init__.py +0 -0
  180. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/configs/dvc_config.py +0 -0
  181. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/configs/mlflow_config.py +0 -0
  182. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/configs/mlops_manager.py +0 -0
  183. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/__init__.py +0 -0
  184. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/app.py +0 -0
  185. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/app_integrated.py +0 -0
  186. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/app_supabase.py +0 -0
  187. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/app_training.py +0 -0
  188. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/cli.py +0 -0
  189. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/common.py +0 -0
  190. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/components/__init__.py +0 -0
  191. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/components/charts.py +0 -0
  192. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/components/metrics.py +0 -0
  193. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/components/tables.py +0 -0
  194. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/overview.py +0 -0
  195. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/__init__.py +0 -0
  196. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/cicd.py +0 -0
  197. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/debug_dependencies.py +0 -0
  198. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/gravity_viz.py +0 -0
  199. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/monte_carlo_predictions.py +0 -0
  200. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/predictions_enhanced.py +0 -0
  201. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/scrapers_and_logs.py +0 -0
  202. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/test_portfolio.py +0 -0
  203. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/trading.py +0 -0
  204. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/pages/workflows.py +0 -0
  205. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/streamlit_extras_utils.py +0 -0
  206. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/styles.py +0 -0
  207. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/utils.py +0 -0
  208. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/dashboard/warning_suppression.py +0 -0
  209. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/data_ingestion/__init__.py +0 -0
  210. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/data_ingestion/api_connectors.py +0 -0
  211. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/data_ingestion/data_pipeline.py +0 -0
  212. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/data_ingestion/stream_processor.py +0 -0
  213. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/database/__init__.py +0 -0
  214. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/database/migrations/env.py +0 -0
  215. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/database/models.py +0 -0
  216. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/database/session.py +0 -0
  217. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/experimentation/__init__.py +0 -0
  218. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/experimentation/ab_testing.py +0 -0
  219. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/features/__init__.py +0 -0
  220. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/features/ensemble_features.py +0 -0
  221. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/features/recommendation_engine.py +0 -0
  222. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/features/stock_features.py +0 -0
  223. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/features/test_feature_engineering.py +0 -0
  224. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/logging.py +0 -0
  225. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/mlops/__init__.py +0 -0
  226. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/mlops/data_versioning.py +0 -0
  227. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/mlops/experiment_tracker.py +0 -0
  228. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/mlops/model_serving.py +0 -0
  229. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/mlops/pipeline_orchestrator.py +0 -0
  230. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/models/__init__.py +0 -0
  231. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/models/base_models.py +0 -0
  232. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/models/ensemble_models.py +0 -0
  233. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/models/recommendation_models.py +0 -0
  234. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/models/test_models.py +0 -0
  235. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/monitoring/__init__.py +0 -0
  236. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/monitoring/drift_detection.py +0 -0
  237. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/monitoring/metrics.py +0 -0
  238. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/optimization/__init__.py +0 -0
  239. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/optimization/optimize.py +0 -0
  240. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/optimization/portfolio_optimizer.py +0 -0
  241. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/predictions/__init__.py +0 -0
  242. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/predictions/monte_carlo.py +0 -0
  243. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/predictions/prediction_engine.py +0 -0
  244. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/preprocessing/__init__.py +0 -0
  245. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/preprocessing/data_cleaners.py +0 -0
  246. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/preprocessing/feature_extractors.py +0 -0
  247. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/preprocessing/ml_pipeline.py +0 -0
  248. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/preprocessing/test_preprocessing.py +0 -0
  249. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/scripts/__init__.py +0 -0
  250. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/scripts/populate_sample_data.py +0 -0
  251. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/serving/__init__.py +0 -0
  252. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/serving/serve.py +0 -0
  253. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/tasks.py +0 -0
  254. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/tests/test_integration.py +0 -0
  255. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/tests/test_training_dashboard.py +0 -0
  256. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/trading/__init__.py +0 -0
  257. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/trading/alpaca_client.py +0 -0
  258. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/trading/migrations.py +0 -0
  259. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/trading/models.py +0 -0
  260. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/trading/paper_trading.py +0 -0
  261. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/trading/risk_management.py +0 -0
  262. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/trading/trading_service.py +0 -0
  263. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/training/__init__.py +0 -0
  264. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/training/train.py +0 -0
  265. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/ml/training/train_model.py +0 -0
  266. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/mygroup/__init__.py +0 -0
  267. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/mygroup/test_cmd.py +0 -0
  268. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/public/__init__.py +0 -0
  269. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/public/commands/__init__.py +0 -0
  270. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/public/oi/oi.py +0 -0
  271. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/public/public.py +0 -0
  272. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/__init__.py +0 -0
  273. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/completion_cmd.py +0 -0
  274. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/env_cmd.py +0 -0
  275. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/health_cmd.py +0 -0
  276. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/logs_cmd.py +0 -0
  277. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/migrate_cmd.py +0 -0
  278. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/store_cmd.py +0 -0
  279. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/test_cmd.py +0 -0
  280. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/self/workflows_cmd.py +0 -0
  281. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/storage/__init__.py +0 -0
  282. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/storage/backends/__init__.py +0 -0
  283. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/storage/backends/ipfs_backend.py +0 -0
  284. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/storage/base.py +0 -0
  285. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/storage/cache.py +0 -0
  286. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/storage/encryption.py +0 -0
  287. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/storage/factory.py +0 -0
  288. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/storage/registry.py +0 -0
  289. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/storage/storacha_cli.py +0 -0
  290. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/__init__.py +0 -0
  291. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/__init__.py +0 -0
  292. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/async_command_database.py +0 -0
  293. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/async_process_manager.py +0 -0
  294. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/client.py +0 -0
  295. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/daemon.py +0 -0
  296. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/daemon_api.py +0 -0
  297. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/enhanced_daemon.py +0 -0
  298. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/process_cli.py +0 -0
  299. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/process_manager.py +0 -0
  300. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/daemon/test_daemon.py +0 -0
  301. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/dashboard/__init__.py +0 -0
  302. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/dashboard/dashboard_cmd.py +0 -0
  303. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/doc_convert.py +0 -0
  304. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/docker/__init__.py +0 -0
  305. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/docker/docker.py +0 -0
  306. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/file/__init__.py +0 -0
  307. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/gcloud/__init__.py +0 -0
  308. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/gcloud/config.toml +0 -0
  309. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/gcloud/gcloud.py +0 -0
  310. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/git_commit/__init__.py +0 -0
  311. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/git_commit/ai_service.py +0 -0
  312. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/interview/__init__.py +0 -0
  313. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/lsh_integration.py +0 -0
  314. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/client.py +0 -0
  315. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/download_and_run_efficient_models.py +0 -0
  316. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/lightweight_embedder.py +0 -0
  317. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/lightweight_model_server.py +0 -0
  318. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/lightweight_test.py +0 -0
  319. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/model_service.py +0 -0
  320. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/ollama_efficient_runner.py +0 -0
  321. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/openai_adapter.py +0 -0
  322. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/pdf_processor.py +0 -0
  323. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/test_efficient_runner.py +0 -0
  324. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/test_example.py +0 -0
  325. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/test_integration.py +0 -0
  326. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/model_service/test_new_features.py +0 -0
  327. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/notebook/__init__.py +0 -0
  328. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/notebook/command_loader.py +0 -0
  329. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/notebook/converter.py +0 -0
  330. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/notebook/executor.py +0 -0
  331. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/notebook/notebook_cmd.py +0 -0
  332. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/notebook/schema.py +0 -0
  333. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/notebook/validator.py +0 -0
  334. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/openai/openai.py +0 -0
  335. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/registry/__init__.py +0 -0
  336. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/registry/registry.py +0 -0
  337. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/repo/__init__.py +0 -0
  338. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/repo/repo.py +0 -0
  339. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/scheduler/__init__.py +0 -0
  340. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/scheduler/cron_parser.py +0 -0
  341. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/scheduler/job.py +0 -0
  342. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/scheduler/models.py +0 -0
  343. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/scheduler/monitor.py +0 -0
  344. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/scheduler/persistence.py +0 -0
  345. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/scheduler/scheduler.py +0 -0
  346. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/scheduler/validation.py +0 -0
  347. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/search/__init__.py +0 -0
  348. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/secrets/__init__.py +0 -0
  349. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/secrets/secrets_cmd.py +0 -0
  350. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/storage/__init__.py +0 -0
  351. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/storage/storage_cmd.py +0 -0
  352. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/sync/__init__.py +0 -0
  353. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/sync/test_cmd.py +0 -0
  354. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/videos/__init__.py +0 -0
  355. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/wakatime/__init__.py +0 -0
  356. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/wakatime/wakatime.py +0 -0
  357. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli/workflow/workflow.py +0 -0
  358. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli_framework.egg-info/dependency_links.txt +0 -0
  359. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli_framework.egg-info/entry_points.txt +0 -0
  360. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli_framework.egg-info/requires.txt +0 -0
  361. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/src/mcli_framework.egg-info/top_level.txt +0 -0
  362. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/__init__.py +0 -0
  363. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_all_commands.py +0 -0
  364. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_app_logs_cmd.py +0 -0
  365. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_app_redis_cmd.py +0 -0
  366. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_logs_cmd.py +0 -0
  367. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_main_app.py +0 -0
  368. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_model_cmd.py +0 -0
  369. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_self_cmd.py +0 -0
  370. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_self_cmd_plugins.py +0 -0
  371. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_self_cmd_utilities.py +0 -0
  372. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_workflow_creation_commands.py +0 -0
  373. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_workflow_file.py +0 -0
  374. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_workflow_gcloud.py +0 -0
  375. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/cli/test_workflow_registry.py +0 -0
  376. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/conftest.py +0 -0
  377. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/e2e/__init__.py +0 -0
  378. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/e2e/test_complete_workflows.py +0 -0
  379. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/e2e/test_model_workflow.py +0 -0
  380. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/e2e/test_new_user_workflow.py +0 -0
  381. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/e2e/test_update_workflow.py +0 -0
  382. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/fixtures/__init__.py +0 -0
  383. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/fixtures/chat_fixtures.py +0 -0
  384. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/fixtures/cli_fixtures.py +0 -0
  385. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/fixtures/command_fixtures.py +0 -0
  386. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/fixtures/data_fixtures.py +0 -0
  387. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/fixtures/db_fixtures.py +0 -0
  388. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/fixtures/model_fixtures.py +0 -0
  389. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/__init__.py +0 -0
  390. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_all_commands_comprehensive.py +0 -0
  391. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_daemon_server.py +0 -0
  392. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_direct_file_execution.py +0 -0
  393. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_e2e_dashboard_lsh_supabase.py +0 -0
  394. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_flask_webapp.py +0 -0
  395. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_folder_workflows_integration.py +0 -0
  396. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_gcloud_services.py +0 -0
  397. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_ml_auth.py +0 -0
  398. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_ml_data_pipeline.py +0 -0
  399. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_ml_models.py +0 -0
  400. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_ml_pipeline.py +0 -0
  401. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_module_imports.py +0 -0
  402. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_notebook_workflows.py +0 -0
  403. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_oi_service.py +0 -0
  404. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_repo_operations.py +0 -0
  405. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_scheduler_integration.py +0 -0
  406. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_service_registry.py +0 -0
  407. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_supabase_live_connection.py +0 -0
  408. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_video_processing.py +0 -0
  409. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_wakatime_api.py +0 -0
  410. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_webapp_full.py +0 -0
  411. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_workflow.py +0 -0
  412. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/integration/test_workflow_commands.py +0 -0
  413. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/performance/__init__.py +0 -0
  414. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/property/__init__.py +0 -0
  415. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/__init__.py +0 -0
  416. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/storage/__init__.py +0 -0
  417. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/storage/test_cache.py +0 -0
  418. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/storage/test_encryption.py +0 -0
  419. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/storage/test_storacha_cli.py +0 -0
  420. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_api_utils.py +0 -0
  421. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_async_process_manager.py +0 -0
  422. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_auth_modules.py +0 -0
  423. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_bug_fixes.py +0 -0
  424. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_command_fixtures.py +0 -0
  425. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_config.py +0 -0
  426. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_correlation_logging.py +0 -0
  427. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_custom_commands.py +0 -0
  428. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_custom_commands_filtering.py +0 -0
  429. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_daemon_api.py +0 -0
  430. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_dashboard_components.py +0 -0
  431. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_dashboard_functions.py +0 -0
  432. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_dashboard_pages.py +0 -0
  433. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_dependencies.py +0 -0
  434. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_doc_convert_workflow.py +0 -0
  435. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_emulator_workflow.py +0 -0
  436. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_erd_generation.py +0 -0
  437. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_erd_generic.py +0 -0
  438. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_erd_imports.py +0 -0
  439. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_folder_workflows.py +0 -0
  440. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_git_commit_workflow.py +0 -0
  441. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_health_cmd.py +0 -0
  442. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_init_mv_cmd.py +0 -0
  443. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_ipfs_retry.py +0 -0
  444. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_language_suffix.py +0 -0
  445. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_lib_auth.py +0 -0
  446. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_lib_files.py +0 -0
  447. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_lib_utils.py +0 -0
  448. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_logger.py +0 -0
  449. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_ml_preprocessing.py +0 -0
  450. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_new_cmd.py +0 -0
  451. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_notebook_command_loader.py +0 -0
  452. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_notebook_executor.py +0 -0
  453. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_optional_deps.py +0 -0
  454. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_paths.py +0 -0
  455. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_pdf_compress.py +0 -0
  456. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_prediction_engine.py +0 -0
  457. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_pyenv.py +0 -0
  458. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_regression.py +0 -0
  459. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_scheduler.py +0 -0
  460. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_scheduler_cron_parser.py +0 -0
  461. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_scheduler_job.py +0 -0
  462. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_scheduler_models.py +0 -0
  463. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_scheduler_monitor.py +0 -0
  464. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_scheduler_persistence.py +0 -0
  465. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_scheduler_validation.py +0 -0
  466. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_script_loader_options.py +0 -0
  467. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_security_command_injection.py +0 -0
  468. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_self_update.py +0 -0
  469. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_service_config.py +0 -0
  470. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_service_health.py +0 -0
  471. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_service_manager.py +0 -0
  472. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_service_state.py +0 -0
  473. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_services_cmd.py +0 -0
  474. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_shell_exceptions.py +0 -0
  475. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_shell_functions.py +0 -0
  476. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_shell_security.py +0 -0
  477. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_store_cmd.py +0 -0
  478. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_supabase_connection.py +0 -0
  479. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_supabase_pagination.py +0 -0
  480. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_sync_cmd.py +0 -0
  481. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_toml_utils.py +0 -0
  482. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_trading_imports.py +0 -0
  483. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_ui_rich.py +0 -0
  484. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_uv_compat.py +0 -0
  485. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_workflow_file_completion.py +0 -0
  486. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/tests/unit/test_workflow_models.py +0 -0
  487. {mcli_framework-8.0.38 → mcli_framework-8.0.39}/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.38
3
+ Version: 8.0.39
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.38"
3
+ version = "8.0.39"
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
@@ -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
@@ -16,7 +16,10 @@ from typing import Optional
16
16
  import click
17
17
  from rich.table import Table
18
18
 
19
- from mcli.lib.constants import SyncMessages
19
+ from mcli.lib.constants import IpfsMessages, SyncMessages
20
+ from mcli.lib.ipfs_utils import ipfs_daemon_running as _ipfs_daemon_running
21
+ from mcli.lib.ipfs_utils import ipfs_initialized as _ipfs_initialized
22
+ from mcli.lib.ipfs_utils import ipfs_installed as _ipfs_installed
20
23
  from mcli.lib.paths import get_custom_commands_dir
21
24
  from mcli.lib.script_loader import ScriptLoader
22
25
  from mcli.lib.ui.styling import console, error, info, success, warning
@@ -46,33 +49,6 @@ def sync_group():
46
49
  pass
47
50
 
48
51
 
49
- # ============================================================
50
- # IPFS Setup Commands
51
- # ============================================================
52
-
53
-
54
- def _ipfs_installed() -> bool:
55
- """Check if IPFS is installed."""
56
- return shutil.which("ipfs") is not None
57
-
58
-
59
- def _ipfs_initialized() -> bool:
60
- """Check if IPFS is initialized (~/.ipfs exists)."""
61
- ipfs_dir = Path.home() / ".ipfs"
62
- return ipfs_dir.exists() and (ipfs_dir / "config").exists()
63
-
64
-
65
- def _ipfs_daemon_running() -> bool:
66
- """Check if IPFS daemon is running."""
67
- try:
68
- import requests
69
-
70
- response = requests.post("http://127.0.0.1:5001/api/v0/id", timeout=2)
71
- return response.status_code == 200
72
- except Exception:
73
- return False
74
-
75
-
76
52
  @sync_group.command(name="init")
77
53
  @click.option("--install", "-i", is_flag=True, help="Install IPFS if not present (requires brew)")
78
54
  @click.option("--foreground", "-f", is_flag=True, help="Run daemon in foreground (blocking)")
@@ -116,6 +92,8 @@ def sync_init(install: bool, foreground: bool):
116
92
  console.print(" [dim]Windows:[/dim] See https://docs.ipfs.tech/install/command-line/")
117
93
  console.print()
118
94
  console.print("[dim]Or run: mcli sync init --install[/dim]")
95
+ console.print()
96
+ console.print(IpfsMessages.SETUP_HINT)
119
97
  return 1
120
98
 
121
99
  success("IPFS is installed")