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

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