mcli-framework 8.0.44__tar.gz → 8.0.46__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 (362) hide show
  1. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/MANIFEST.in +2 -6
  2. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/PKG-INFO +20 -18
  3. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/pyproject.toml +24 -25
  4. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/commands_cmd.py +47 -20
  5. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/main.py +24 -0
  6. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/model_cmd.py +10 -34
  7. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/new_cmd.py +2 -2
  8. mcli_framework-8.0.46/src/mcli/app/setup_cmd.py +187 -0
  9. mcli_framework-8.0.46/src/mcli/app/source_sync_cmd.py +335 -0
  10. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/sync_cmd.py +105 -36
  11. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/api/api.py +3 -3
  12. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/api/daemon_client.py +9 -0
  13. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/config/__init__.py +17 -1
  14. mcli_framework-8.0.46/src/mcli/lib/config/settings.py +192 -0
  15. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/constants/defaults.py +10 -0
  16. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/constants/env.py +1 -0
  17. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/constants/messages.py +21 -0
  18. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/ipfs_sync.py +227 -0
  19. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/ipfs_utils.py +87 -0
  20. mcli_framework-8.0.46/src/mcli/lib/ipns_manager.py +206 -0
  21. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/pickles/pickles.py +15 -1
  22. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/script_loader.py +18 -2
  23. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/secrets/manager.py +12 -3
  24. mcli_framework-8.0.46/src/mcli/self/release_notes_cmd.py +304 -0
  25. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/self_cmd.py +8 -0
  26. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/daemon_api.py +14 -2
  27. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli_framework.egg-info/PKG-INFO +20 -18
  28. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli_framework.egg-info/SOURCES.txt +6 -128
  29. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli_framework.egg-info/requires.txt +19 -17
  30. mcli_framework-8.0.44/.github/dependabot.yml +0 -49
  31. mcli_framework-8.0.44/.github/dependency-review-config.yml +0 -17
  32. mcli_framework-8.0.44/.github/workflows/build.yml +0 -102
  33. mcli_framework-8.0.44/.github/workflows/ci.yml +0 -275
  34. mcli_framework-8.0.44/.github/workflows/codeql.yml +0 -43
  35. mcli_framework-8.0.44/.github/workflows/docs-links.yml +0 -48
  36. mcli_framework-8.0.44/.github/workflows/publish-self-hosted.yml +0 -244
  37. mcli_framework-8.0.44/.github/workflows/publish.yml +0 -225
  38. mcli_framework-8.0.44/.github/workflows/release.yml +0 -91
  39. mcli_framework-8.0.44/.github/workflows/security.yml +0 -128
  40. mcli_framework-8.0.44/.github/workflows/test.yml +0 -154
  41. mcli_framework-8.0.44/tests/cli/__init__.py +0 -0
  42. mcli_framework-8.0.44/tests/cli/test_all_commands.py +0 -7
  43. mcli_framework-8.0.44/tests/cli/test_app_logs_cmd.py +0 -206
  44. mcli_framework-8.0.44/tests/cli/test_app_redis_cmd.py +0 -276
  45. mcli_framework-8.0.44/tests/cli/test_logs_cmd.py +0 -287
  46. mcli_framework-8.0.44/tests/cli/test_main_app.py +0 -36
  47. mcli_framework-8.0.44/tests/cli/test_model_cmd.py +0 -619
  48. mcli_framework-8.0.44/tests/cli/test_self_cmd.py +0 -788
  49. mcli_framework-8.0.44/tests/cli/test_self_cmd_plugins.py +0 -273
  50. mcli_framework-8.0.44/tests/cli/test_self_cmd_utilities.py +0 -225
  51. mcli_framework-8.0.44/tests/cli/test_workflow_creation_commands.py +0 -109
  52. mcli_framework-8.0.44/tests/cli/test_workflow_file.py +0 -137
  53. mcli_framework-8.0.44/tests/cli/test_workflow_gcloud.py +0 -120
  54. mcli_framework-8.0.44/tests/cli/test_workflow_registry.py +0 -231
  55. mcli_framework-8.0.44/tests/conftest.py +0 -149
  56. mcli_framework-8.0.44/tests/e2e/__init__.py +0 -0
  57. mcli_framework-8.0.44/tests/e2e/test_complete_workflows.py +0 -422
  58. mcli_framework-8.0.44/tests/e2e/test_model_workflow.py +0 -155
  59. mcli_framework-8.0.44/tests/e2e/test_new_user_workflow.py +0 -144
  60. mcli_framework-8.0.44/tests/e2e/test_update_workflow.py +0 -195
  61. mcli_framework-8.0.44/tests/fixtures/__init__.py +0 -75
  62. mcli_framework-8.0.44/tests/fixtures/chat_fixtures.py +0 -82
  63. mcli_framework-8.0.44/tests/fixtures/cli_fixtures.py +0 -93
  64. mcli_framework-8.0.44/tests/fixtures/command_fixtures.py +0 -325
  65. mcli_framework-8.0.44/tests/fixtures/data_fixtures.py +0 -97
  66. mcli_framework-8.0.44/tests/fixtures/db_fixtures.py +0 -100
  67. mcli_framework-8.0.44/tests/fixtures/model_fixtures.py +0 -66
  68. mcli_framework-8.0.44/tests/integration/__init__.py +0 -0
  69. mcli_framework-8.0.44/tests/integration/test_all_commands_comprehensive.py +0 -878
  70. mcli_framework-8.0.44/tests/integration/test_daemon_server.py +0 -824
  71. mcli_framework-8.0.44/tests/integration/test_direct_file_execution.py +0 -257
  72. mcli_framework-8.0.44/tests/integration/test_e2e_dashboard_lsh_supabase.py +0 -695
  73. mcli_framework-8.0.44/tests/integration/test_flask_webapp.py +0 -7
  74. mcli_framework-8.0.44/tests/integration/test_folder_workflows_integration.py +0 -382
  75. mcli_framework-8.0.44/tests/integration/test_gcloud_services.py +0 -58
  76. mcli_framework-8.0.44/tests/integration/test_ml_data_pipeline.py +0 -642
  77. mcli_framework-8.0.44/tests/integration/test_module_imports.py +0 -132
  78. mcli_framework-8.0.44/tests/integration/test_notebook_workflows.py +0 -503
  79. mcli_framework-8.0.44/tests/integration/test_oi_service.py +0 -10
  80. mcli_framework-8.0.44/tests/integration/test_repo_operations.py +0 -77
  81. mcli_framework-8.0.44/tests/integration/test_scheduler_integration.py +0 -482
  82. mcli_framework-8.0.44/tests/integration/test_service_registry.py +0 -141
  83. mcli_framework-8.0.44/tests/integration/test_video_processing.py +0 -69
  84. mcli_framework-8.0.44/tests/integration/test_wakatime_api.py +0 -10
  85. mcli_framework-8.0.44/tests/integration/test_webapp_full.py +0 -7
  86. mcli_framework-8.0.44/tests/integration/test_workflow.py +0 -7
  87. mcli_framework-8.0.44/tests/integration/test_workflow_commands.py +0 -7
  88. mcli_framework-8.0.44/tests/performance/__init__.py +0 -0
  89. mcli_framework-8.0.44/tests/property/__init__.py +0 -0
  90. mcli_framework-8.0.44/tests/unit/__init__.py +0 -0
  91. mcli_framework-8.0.44/tests/unit/storage/__init__.py +0 -1
  92. mcli_framework-8.0.44/tests/unit/storage/test_cache.py +0 -244
  93. mcli_framework-8.0.44/tests/unit/storage/test_encryption.py +0 -118
  94. mcli_framework-8.0.44/tests/unit/storage/test_storacha_cli.py +0 -285
  95. mcli_framework-8.0.44/tests/unit/test_api_utils.py +0 -98
  96. mcli_framework-8.0.44/tests/unit/test_async_process_manager.py +0 -571
  97. mcli_framework-8.0.44/tests/unit/test_auth_modules.py +0 -324
  98. mcli_framework-8.0.44/tests/unit/test_bug_fixes.py +0 -41
  99. mcli_framework-8.0.44/tests/unit/test_command_fixtures.py +0 -240
  100. mcli_framework-8.0.44/tests/unit/test_config.py +0 -98
  101. mcli_framework-8.0.44/tests/unit/test_correlation_logging.py +0 -698
  102. mcli_framework-8.0.44/tests/unit/test_custom_commands.py +0 -338
  103. mcli_framework-8.0.44/tests/unit/test_custom_commands_filtering.py +0 -164
  104. mcli_framework-8.0.44/tests/unit/test_daemon_api.py +0 -266
  105. mcli_framework-8.0.44/tests/unit/test_dependencies.py +0 -60
  106. mcli_framework-8.0.44/tests/unit/test_doc_convert_workflow.py +0 -259
  107. mcli_framework-8.0.44/tests/unit/test_emulator_workflow.py +0 -618
  108. mcli_framework-8.0.44/tests/unit/test_erd_generation.py +0 -1365
  109. mcli_framework-8.0.44/tests/unit/test_erd_generic.py +0 -254
  110. mcli_framework-8.0.44/tests/unit/test_erd_imports.py +0 -21
  111. mcli_framework-8.0.44/tests/unit/test_folder_workflows.py +0 -401
  112. mcli_framework-8.0.44/tests/unit/test_git_commit_workflow.py +0 -343
  113. mcli_framework-8.0.44/tests/unit/test_health_cmd.py +0 -589
  114. mcli_framework-8.0.44/tests/unit/test_import_cmd.py +0 -866
  115. mcli_framework-8.0.44/tests/unit/test_init_mv_cmd.py +0 -293
  116. mcli_framework-8.0.44/tests/unit/test_ipfs_cmd.py +0 -320
  117. mcli_framework-8.0.44/tests/unit/test_ipfs_retry.py +0 -233
  118. mcli_framework-8.0.44/tests/unit/test_language_suffix.py +0 -467
  119. mcli_framework-8.0.44/tests/unit/test_lib_auth.py +0 -10
  120. mcli_framework-8.0.44/tests/unit/test_lib_files.py +0 -55
  121. mcli_framework-8.0.44/tests/unit/test_lib_utils.py +0 -9
  122. mcli_framework-8.0.44/tests/unit/test_logger.py +0 -214
  123. mcli_framework-8.0.44/tests/unit/test_new_cmd.py +0 -819
  124. mcli_framework-8.0.44/tests/unit/test_notebook_command_loader.py +0 -525
  125. mcli_framework-8.0.44/tests/unit/test_notebook_executor.py +0 -233
  126. mcli_framework-8.0.44/tests/unit/test_optional_deps.py +0 -211
  127. mcli_framework-8.0.44/tests/unit/test_paths.py +0 -202
  128. mcli_framework-8.0.44/tests/unit/test_pdf_compress.py +0 -257
  129. mcli_framework-8.0.44/tests/unit/test_pyenv.py +0 -427
  130. mcli_framework-8.0.44/tests/unit/test_regression.py +0 -129
  131. mcli_framework-8.0.44/tests/unit/test_scheduler.py +0 -439
  132. mcli_framework-8.0.44/tests/unit/test_scheduler_cron_parser.py +0 -509
  133. mcli_framework-8.0.44/tests/unit/test_scheduler_job.py +0 -505
  134. mcli_framework-8.0.44/tests/unit/test_scheduler_models.py +0 -419
  135. mcli_framework-8.0.44/tests/unit/test_scheduler_monitor.py +0 -509
  136. mcli_framework-8.0.44/tests/unit/test_scheduler_persistence.py +0 -709
  137. mcli_framework-8.0.44/tests/unit/test_scheduler_validation.py +0 -390
  138. mcli_framework-8.0.44/tests/unit/test_script_loader_options.py +0 -210
  139. mcli_framework-8.0.44/tests/unit/test_security_command_injection.py +0 -225
  140. mcli_framework-8.0.44/tests/unit/test_self_update.py +0 -200
  141. mcli_framework-8.0.44/tests/unit/test_service_config.py +0 -82
  142. mcli_framework-8.0.44/tests/unit/test_service_health.py +0 -88
  143. mcli_framework-8.0.44/tests/unit/test_service_manager.py +0 -150
  144. mcli_framework-8.0.44/tests/unit/test_service_state.py +0 -93
  145. mcli_framework-8.0.44/tests/unit/test_services_cmd.py +0 -162
  146. mcli_framework-8.0.44/tests/unit/test_shell_exceptions.py +0 -428
  147. mcli_framework-8.0.44/tests/unit/test_shell_functions.py +0 -329
  148. mcli_framework-8.0.44/tests/unit/test_shell_security.py +0 -215
  149. mcli_framework-8.0.44/tests/unit/test_store_cmd.py +0 -445
  150. mcli_framework-8.0.44/tests/unit/test_sync_cmd.py +0 -266
  151. mcli_framework-8.0.44/tests/unit/test_toml_utils.py +0 -192
  152. mcli_framework-8.0.44/tests/unit/test_ui_rich.py +0 -22
  153. mcli_framework-8.0.44/tests/unit/test_uv_compat.py +0 -224
  154. mcli_framework-8.0.44/tests/unit/test_workflow_file_completion.py +0 -219
  155. mcli_framework-8.0.44/tests/unit/test_workflow_models.py +0 -337
  156. mcli_framework-8.0.44/tests/unit/workflow/test_notebook.py +0 -443
  157. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/LICENSE +0 -0
  158. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/README.md +0 -0
  159. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/llms-full.txt +0 -0
  160. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/llms.txt +0 -0
  161. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/mcli_rust/Cargo.toml +0 -0
  162. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/mcli_rust/src/command_parser.rs +0 -0
  163. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/mcli_rust/src/file_watcher.rs +0 -0
  164. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/mcli_rust/src/lib.rs +0 -0
  165. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/mcli_rust/src/process_manager.rs +0 -0
  166. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/mcli_rust/src/tfidf.rs +0 -0
  167. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/setup.cfg +0 -0
  168. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/__init__.py +0 -0
  169. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/__init__.py +0 -0
  170. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/completion_helpers.py +0 -0
  171. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/context_cmd.py +0 -0
  172. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/create_cmd.py +0 -0
  173. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/delete_cmd.py +0 -0
  174. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/edit_cmd.py +0 -0
  175. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/import_cmd.py +0 -0
  176. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/init_cmd.py +0 -0
  177. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/list_cmd.py +0 -0
  178. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/migrate_cmd.py +0 -0
  179. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/model/__init__.py +0 -0
  180. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/model/model.py +0 -0
  181. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/mv_cmd.py +0 -0
  182. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/remove_cmd.py +0 -0
  183. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/rm_cmd.py +0 -0
  184. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/search_cmd.py +0 -0
  185. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/services_cmd.py +0 -0
  186. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/video/__init__.py +0 -0
  187. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/app/video/video.py +0 -0
  188. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/config.toml +0 -0
  189. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/__init__.py +0 -0
  190. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/api/__init__.py +0 -0
  191. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/api/daemon_client_local.py +0 -0
  192. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/api/daemon_decorator.py +0 -0
  193. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/api/mcli_decorators.py +0 -0
  194. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/__init__.py +0 -0
  195. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/auth.py +0 -0
  196. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/aws_manager.py +0 -0
  197. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/azure_manager.py +0 -0
  198. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/credential_manager.py +0 -0
  199. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/gcp_manager.py +0 -0
  200. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/key_manager.py +0 -0
  201. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/mcli_manager.py +0 -0
  202. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/token_manager.py +0 -0
  203. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/auth/token_util.py +0 -0
  204. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/config/config.py +0 -0
  205. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/constants/__init__.py +0 -0
  206. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/constants/commands.py +0 -0
  207. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/constants/paths.py +0 -0
  208. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/constants/scripts.py +0 -0
  209. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/constants/storage.py +0 -0
  210. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/custom_commands.py +0 -0
  211. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/discovery/__init__.py +0 -0
  212. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/discovery/command_discovery.py +0 -0
  213. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/erd/__init__.py +0 -0
  214. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/erd/erd.py +0 -0
  215. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/erd/generate_graph.py +0 -0
  216. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/errors.py +0 -0
  217. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/feature_detection.py +0 -0
  218. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/files/__init__.py +0 -0
  219. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/files/files.py +0 -0
  220. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/folder_workflows.py +0 -0
  221. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/fs/__init__.py +0 -0
  222. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/fs/fs.py +0 -0
  223. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/lib.py +0 -0
  224. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/logger/__init__.py +0 -0
  225. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/logger/correlation.py +0 -0
  226. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/logger/logger.py +0 -0
  227. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/logger/structured.py +0 -0
  228. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/optional_deps.py +0 -0
  229. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/paths.py +0 -0
  230. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/performance/__init__.py +0 -0
  231. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/performance/optimizer.py +0 -0
  232. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/performance/rust_bridge.py +0 -0
  233. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/performance/uvloop_config.py +0 -0
  234. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/pickles/__init__.py +0 -0
  235. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/pyenv/__init__.py +0 -0
  236. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/pyenv/deps.py +0 -0
  237. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/pyenv/manager.py +0 -0
  238. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/pyenv/venv.py +0 -0
  239. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/script_sync.py +0 -0
  240. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/script_watcher.py +0 -0
  241. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/search/cached_vectorizer.py +0 -0
  242. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/secrets/__init__.py +0 -0
  243. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/secrets/commands.py +0 -0
  244. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/secrets/repl.py +0 -0
  245. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/secrets/store.py +0 -0
  246. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/__init__.py +0 -0
  247. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/config.py +0 -0
  248. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/data_pipeline.py +0 -0
  249. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/health.py +0 -0
  250. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/lsh_client.py +0 -0
  251. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/manager.py +0 -0
  252. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/redis_service.py +0 -0
  253. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/registry.py +0 -0
  254. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/state.py +0 -0
  255. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/services/supervisor.py +0 -0
  256. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/shell/__init__.py +0 -0
  257. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/shell/exceptions.py +0 -0
  258. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/shell/shell.py +0 -0
  259. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/templates/__init__.py +0 -0
  260. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/templates/command_templates.py +0 -0
  261. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/toml/__init__.py +0 -0
  262. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/toml/toml.py +0 -0
  263. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/types.py +0 -0
  264. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/ui/styling.py +0 -0
  265. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/ui/visual_effects.py +0 -0
  266. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/watcher/__init__.py +0 -0
  267. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/watcher/watcher.py +0 -0
  268. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/workflow_models.py +0 -0
  269. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/lib/workspace_registry.py +0 -0
  270. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/mygroup/__init__.py +0 -0
  271. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/mygroup/test_cmd.py +0 -0
  272. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/public/__init__.py +0 -0
  273. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/public/commands/__init__.py +0 -0
  274. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/public/oi/oi.py +0 -0
  275. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/public/public.py +0 -0
  276. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/__init__.py +0 -0
  277. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/completion_cmd.py +0 -0
  278. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/env_cmd.py +0 -0
  279. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/health_cmd.py +0 -0
  280. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/ipfs_cmd.py +0 -0
  281. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/logs_cmd.py +0 -0
  282. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/migrate_cmd.py +0 -0
  283. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/store_cmd.py +0 -0
  284. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/test_cmd.py +0 -0
  285. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/self/workflows_cmd.py +0 -0
  286. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/storage/__init__.py +0 -0
  287. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/storage/backends/__init__.py +0 -0
  288. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/storage/backends/ipfs_backend.py +0 -0
  289. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/storage/base.py +0 -0
  290. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/storage/cache.py +0 -0
  291. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/storage/encryption.py +0 -0
  292. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/storage/factory.py +0 -0
  293. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/storage/registry.py +0 -0
  294. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/storage/storacha_cli.py +0 -0
  295. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/__init__.py +0 -0
  296. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/__init__.py +0 -0
  297. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/async_command_database.py +0 -0
  298. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/async_process_manager.py +0 -0
  299. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/client.py +0 -0
  300. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/daemon.py +0 -0
  301. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/enhanced_daemon.py +0 -0
  302. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/process_cli.py +0 -0
  303. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/process_manager.py +0 -0
  304. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/daemon/test_daemon.py +0 -0
  305. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/doc_convert.py +0 -0
  306. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/docker/__init__.py +0 -0
  307. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/docker/docker.py +0 -0
  308. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/file/__init__.py +0 -0
  309. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/gcloud/__init__.py +0 -0
  310. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/gcloud/config.toml +0 -0
  311. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/gcloud/gcloud.py +0 -0
  312. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/git_commit/__init__.py +0 -0
  313. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/git_commit/ai_service.py +0 -0
  314. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/interview/__init__.py +0 -0
  315. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/lsh_integration.py +0 -0
  316. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/client.py +0 -0
  317. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/download_and_run_efficient_models.py +0 -0
  318. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/lightweight_embedder.py +0 -0
  319. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/lightweight_model_server.py +0 -0
  320. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/lightweight_test.py +0 -0
  321. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/model_service.py +0 -0
  322. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/ollama_efficient_runner.py +0 -0
  323. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/openai_adapter.py +0 -0
  324. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/pdf_processor.py +0 -0
  325. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/test_efficient_runner.py +0 -0
  326. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/test_example.py +0 -0
  327. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/test_integration.py +0 -0
  328. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/model_service/test_new_features.py +0 -0
  329. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/notebook/__init__.py +0 -0
  330. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/notebook/command_loader.py +0 -0
  331. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/notebook/converter.py +0 -0
  332. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/notebook/executor.py +0 -0
  333. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/notebook/notebook_cmd.py +0 -0
  334. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/notebook/schema.py +0 -0
  335. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/notebook/validator.py +0 -0
  336. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/openai/openai.py +0 -0
  337. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/registry/__init__.py +0 -0
  338. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/registry/registry.py +0 -0
  339. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/repo/__init__.py +0 -0
  340. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/repo/repo.py +0 -0
  341. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/scheduler/__init__.py +0 -0
  342. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/scheduler/cron_parser.py +0 -0
  343. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/scheduler/job.py +0 -0
  344. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/scheduler/models.py +0 -0
  345. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/scheduler/monitor.py +0 -0
  346. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/scheduler/persistence.py +0 -0
  347. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/scheduler/scheduler.py +0 -0
  348. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/scheduler/validation.py +0 -0
  349. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/search/__init__.py +0 -0
  350. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/secrets/__init__.py +0 -0
  351. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/secrets/secrets_cmd.py +0 -0
  352. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/storage/__init__.py +0 -0
  353. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/storage/storage_cmd.py +0 -0
  354. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/sync/__init__.py +0 -0
  355. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/sync/test_cmd.py +0 -0
  356. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/videos/__init__.py +0 -0
  357. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/wakatime/__init__.py +0 -0
  358. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/wakatime/wakatime.py +0 -0
  359. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli/workflow/workflow.py +0 -0
  360. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli_framework.egg-info/dependency_links.txt +0 -0
  361. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli_framework.egg-info/entry_points.txt +0 -0
  362. {mcli_framework-8.0.44 → mcli_framework-8.0.46}/src/mcli_framework.egg-info/top_level.txt +0 -0
@@ -17,12 +17,8 @@ recursive-include src/mcli *.toml
17
17
  graft mcli_rust/src
18
18
  include mcli_rust/Cargo.toml
19
19
 
20
- # Include GitHub workflows and configuration
21
- recursive-include .github *.yml *.yaml
22
-
23
- # Include tests (optional, for development)
24
- recursive-include tests *.py
25
- include tests/*.ini
20
+ # Exclude CI/test files from distribution (not needed for end users)
21
+ # GitHub workflows and test files are available in the source repository
26
22
 
27
23
  # Exclude build artifacts
28
24
  prune build/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcli-framework
3
- Version: 8.0.44
3
+ Version: 8.0.46
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>
@@ -37,10 +37,12 @@ Requires-Python: >=3.10
37
37
  Description-Content-Type: text/markdown
38
38
  License-File: LICENSE
39
39
  Requires-Dist: click<9.0.0,>=8.1.7
40
- Requires-Dist: rich>=14.0.0
40
+ Requires-Dist: rich<15.0.0,>=14.0.0
41
41
  Requires-Dist: requests<3.0.0,>=2.31.0
42
- Requires-Dist: tomli>=2.2.1
43
- Requires-Dist: python-dotenv>=1.1.1
42
+ Requires-Dist: tomli<3.0.0,>=2.2.1
43
+ Requires-Dist: python-dotenv<2.0.0,>=1.1.1
44
+ Requires-Dist: pydantic<3.0.0,>=2.0.0
45
+ Requires-Dist: pydantic-settings<3.0.0,>=2.0.0
44
46
  Requires-Dist: watchdog<4.0.0,>=3.0.0
45
47
  Requires-Dist: tqdm<5.0.0,>=4.66.1
46
48
  Requires-Dist: humanize<5.0.0,>=4.9.0
@@ -48,22 +50,22 @@ Requires-Dist: psutil<6.0.0,>=5.9.0
48
50
  Requires-Dist: inquirerpy<0.4.0,>=0.3.4
49
51
  Requires-Dist: gitpython<4.0.0,>=3.1.40
50
52
  Requires-Dist: prompt-toolkit<4.0.0,>=3.0.0
51
- Requires-Dist: aiohttp>=3.13.3
52
- Requires-Dist: httpx>=0.28.1
53
- Requires-Dist: websockets>=12.0
54
- Requires-Dist: beautifulsoup4>=4.13.5
55
- Requires-Dist: fuzzywuzzy>=0.18.0
53
+ Requires-Dist: aiohttp<4.0.0,>=3.13.3
54
+ Requires-Dist: httpx<1.0.0,>=0.28.1
55
+ Requires-Dist: websockets<14.0.0,>=12.0
56
+ Requires-Dist: beautifulsoup4<5.0.0,>=4.13.5
57
+ Requires-Dist: fuzzywuzzy<1.0.0,>=0.18.0
56
58
  Requires-Dist: openai<2.0.0,>=1.3.0
57
- Requires-Dist: anthropic>=0.60.0
58
- Requires-Dist: ollama>=0.5.3
59
+ Requires-Dist: anthropic<1.0.0,>=0.60.0
60
+ Requires-Dist: ollama<1.0.0,>=0.5.3
59
61
  Requires-Dist: ipython<9.0.0,>=8.12.0
60
- Requires-Dist: fastapi>=0.110.0
61
- Requires-Dist: uvicorn>=0.27.0
62
- Requires-Dist: uvloop>=0.19.0
63
- Requires-Dist: aiosqlite>=0.20.0
64
- Requires-Dist: redis>=5.0.0
65
- Requires-Dist: aiohttp-sse-client>=0.2.1
66
- Requires-Dist: aiomqtt>=2.0.0
62
+ Requires-Dist: fastapi<1.0.0,>=0.110.0
63
+ Requires-Dist: uvicorn<1.0.0,>=0.27.0
64
+ Requires-Dist: uvloop<1.0.0,>=0.19.0
65
+ Requires-Dist: aiosqlite<1.0.0,>=0.20.0
66
+ Requires-Dist: redis<6.0.0,>=5.0.0
67
+ Requires-Dist: aiohttp-sse-client<1.0.0,>=0.2.1
68
+ Requires-Dist: aiomqtt<3.0.0,>=2.0.0
67
69
  Provides-Extra: dev
68
70
  Requires-Dist: pytest>=8.4.1; extra == "dev"
69
71
  Requires-Dist: pytest-cov<5.0.0,>=4.1.0; extra == "dev"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mcli-framework"
3
- version = "8.0.44"
3
+ version = "8.0.46"
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"
@@ -37,10 +37,12 @@ classifiers = [
37
37
  dependencies = [
38
38
  # Core CLI dependencies
39
39
  "click>=8.1.7,<9.0.0",
40
- "rich>=14.0.0",
40
+ "rich>=14.0.0,<15.0.0",
41
41
  "requests>=2.31.0,<3.0.0",
42
- "tomli>=2.2.1",
43
- "python-dotenv>=1.1.1",
42
+ "tomli>=2.2.1,<3.0.0",
43
+ "python-dotenv>=1.1.1,<2.0.0",
44
+ "pydantic>=2.0.0,<3.0.0",
45
+ "pydantic-settings>=2.0.0,<3.0.0",
44
46
  # Core utilities
45
47
  "watchdog>=3.0.0,<4.0.0",
46
48
  "tqdm>=4.66.1,<5.0.0",
@@ -50,25 +52,25 @@ dependencies = [
50
52
  "gitpython>=3.1.40,<4.0.0",
51
53
  "prompt-toolkit>=3.0.0,<4.0.0",
52
54
  # Basic HTTP/async support
53
- "aiohttp>=3.13.3", # CVE-2025-69223 through CVE-2025-69230 fixes
54
- "httpx>=0.28.1",
55
- "websockets>=12.0",
55
+ "aiohttp>=3.13.3,<4.0.0", # CVE-2025-69223 through CVE-2025-69230 fixes
56
+ "httpx>=0.28.1,<1.0.0",
57
+ "websockets>=12.0,<14.0.0",
56
58
  # Data parsing
57
- "beautifulsoup4>=4.13.5",
58
- "fuzzywuzzy>=0.18.0",
59
+ "beautifulsoup4>=4.13.5,<5.0.0",
60
+ "fuzzywuzzy>=0.18.0,<1.0.0",
59
61
  # Chat and AI capabilities
60
62
  "openai>=1.3.0,<2.0.0",
61
- "anthropic>=0.60.0",
62
- "ollama>=0.5.3",
63
+ "anthropic>=0.60.0,<1.0.0",
64
+ "ollama>=0.5.3,<1.0.0",
63
65
  "ipython>=8.12.0,<9.0.0",
64
66
  # Enhanced async/performance features
65
- "fastapi>=0.110.0",
66
- "uvicorn>=0.27.0",
67
- "uvloop>=0.19.0",
68
- "aiosqlite>=0.20.0",
69
- "redis>=5.0.0",
70
- "aiohttp-sse-client>=0.2.1",
71
- "aiomqtt>=2.0.0",
67
+ "fastapi>=0.110.0,<1.0.0",
68
+ "uvicorn>=0.27.0,<1.0.0",
69
+ "uvloop>=0.19.0,<1.0.0",
70
+ "aiosqlite>=0.20.0,<1.0.0",
71
+ "redis>=5.0.0,<6.0.0",
72
+ "aiohttp-sse-client>=0.2.1,<1.0.0",
73
+ "aiomqtt>=2.0.0,<3.0.0",
72
74
  ]
73
75
 
74
76
  [project.urls]
@@ -177,20 +179,15 @@ disable_error_code = [
177
179
  "index",
178
180
  "type-arg",
179
181
  "override",
180
- "comparison-overlap",
181
- "redundant-expr",
182
182
  "no-any-return",
183
183
  "has-type",
184
184
  "valid-type",
185
185
  "type-var",
186
186
  "dict-item",
187
187
  "call-overload",
188
- "empty-body",
189
188
  "no-redef",
190
189
  "abstract",
191
190
  "list-item",
192
- "str-bytes-safe",
193
- "func-returns-value",
194
191
  ]
195
192
 
196
193
  # Module discovery
@@ -259,6 +256,8 @@ requires = ["setuptools>=65.0.0", "wheel>=0.40.0"]
259
256
  build-backend = "setuptools.build_meta"
260
257
 
261
258
  [dependency-groups]
259
+ # NOTE: This is the primary dev dependency specification (PEP 735).
260
+ # [project.optional-dependencies] dev is kept for pip compatibility.
262
261
  dev = [
263
262
  "black>=25.0.0,<26.0.0", # Pin to 25.x to match lockfile
264
263
  "isort>=5.13.2",
@@ -320,7 +319,7 @@ precision = 2
320
319
  skip_covered = false
321
320
  skip_empty = false
322
321
  # Fail if coverage is below threshold
323
- fail_under = 25.0
322
+ fail_under = 50.0
324
323
 
325
324
  [tool.coverage.html]
326
325
  directory = "htmlcov"
@@ -338,7 +337,7 @@ addopts = [
338
337
  "--cov-report=html",
339
338
  "--cov-report=xml",
340
339
  "--cov-branch",
341
- "--cov-fail-under=80",
340
+ "--cov-fail-under=50",
342
341
  ]
343
342
  testpaths = ["tests"]
344
343
  python_files = ["test_*.py", "*_test.py"]
@@ -353,7 +353,9 @@ def init_store(path, remote):
353
353
  # Initialize git if not already initialized
354
354
  git_dir = store_path / ".git"
355
355
  if not git_dir.exists():
356
- subprocess.run(["git", "init"], cwd=store_path, check=True, capture_output=True)
356
+ subprocess.run(
357
+ ["git", "init"], cwd=store_path, check=True, capture_output=True, timeout=60
358
+ )
357
359
  success(f"Initialized git repository at {store_path}")
358
360
 
359
361
  # Create .gitignore
@@ -395,7 +397,10 @@ Last updated: {datetime.now().isoformat()}
395
397
  # Add remote if provided
396
398
  if remote:
397
399
  subprocess.run(
398
- ["git", "remote", "add", "origin", remote], cwd=store_path, check=True
400
+ ["git", "remote", "add", "origin", remote],
401
+ cwd=store_path,
402
+ check=True,
403
+ timeout=60,
399
404
  )
400
405
  success(f"Added remote: {remote}")
401
406
  else:
@@ -455,11 +460,15 @@ def push_commands(message, all, is_global):
455
460
  success(f"Copied {copied_count} items to store")
456
461
 
457
462
  # Git add, commit, push
458
- subprocess.run(["git", "add", "."], cwd=store_path, check=True)
463
+ subprocess.run(["git", "add", "."], cwd=store_path, check=True, timeout=60)
459
464
 
460
465
  # Check if there are changes
461
466
  result = subprocess.run(
462
- ["git", "status", "--porcelain"], cwd=store_path, capture_output=True, text=True
467
+ ["git", "status", "--porcelain"],
468
+ cwd=store_path,
469
+ capture_output=True,
470
+ text=True,
471
+ timeout=60,
463
472
  )
464
473
 
465
474
  if not result.stdout.strip():
@@ -468,12 +477,14 @@ def push_commands(message, all, is_global):
468
477
 
469
478
  # Commit with message
470
479
  commit_msg = message or f"Update commands {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
471
- subprocess.run(["git", "commit", "-m", commit_msg], cwd=store_path, check=True)
480
+ subprocess.run(["git", "commit", "-m", commit_msg], cwd=store_path, check=True, timeout=60)
472
481
  success(f"Committed changes: {commit_msg}")
473
482
 
474
483
  # Push to remote if configured
475
484
  try:
476
- subprocess.run(["git", "push"], cwd=store_path, check=True, capture_output=True)
485
+ subprocess.run(
486
+ ["git", "push"], cwd=store_path, check=True, capture_output=True, timeout=60
487
+ )
477
488
  success("Pushed to remote")
478
489
  except subprocess.CalledProcessError:
479
490
  warning("No remote configured or push failed. Commands committed locally.")
@@ -502,7 +513,7 @@ def pull_commands(force, is_global):
502
513
 
503
514
  # Pull from remote
504
515
  try:
505
- subprocess.run(["git", "pull"], cwd=store_path, check=True)
516
+ subprocess.run(["git", "pull"], cwd=store_path, check=True, timeout=60)
506
517
  success("Pulled latest changes from remote")
507
518
  except subprocess.CalledProcessError:
508
519
  warning("No remote configured or pull failed. Using local store.")
@@ -561,7 +572,9 @@ def sync_commands(message, is_global):
561
572
  # First pull
562
573
  info("Pulling latest changes...")
563
574
  try:
564
- subprocess.run(["git", "pull"], cwd=store_path, check=True, capture_output=True)
575
+ subprocess.run(
576
+ ["git", "pull"], cwd=store_path, check=True, capture_output=True, timeout=60
577
+ )
565
578
  success("Pulled from remote")
566
579
  except subprocess.CalledProcessError:
567
580
  warning("No remote or pull failed")
@@ -581,7 +594,11 @@ def sync_commands(message, is_global):
581
594
 
582
595
  # Check for changes
583
596
  result = subprocess.run(
584
- ["git", "status", "--porcelain"], cwd=store_path, capture_output=True, text=True
597
+ ["git", "status", "--porcelain"],
598
+ cwd=store_path,
599
+ capture_output=True,
600
+ text=True,
601
+ timeout=60,
585
602
  )
586
603
 
587
604
  if not result.stdout.strip():
@@ -589,12 +606,14 @@ def sync_commands(message, is_global):
589
606
  return
590
607
 
591
608
  # Commit and push
592
- subprocess.run(["git", "add", "."], cwd=store_path, check=True)
609
+ subprocess.run(["git", "add", "."], cwd=store_path, check=True, timeout=60)
593
610
  commit_msg = message or f"Sync commands {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
594
- subprocess.run(["git", "commit", "-m", commit_msg], cwd=store_path, check=True)
611
+ subprocess.run(["git", "commit", "-m", commit_msg], cwd=store_path, check=True, timeout=60)
595
612
 
596
613
  try:
597
- subprocess.run(["git", "push"], cwd=store_path, check=True, capture_output=True)
614
+ subprocess.run(
615
+ ["git", "push"], cwd=store_path, check=True, capture_output=True, timeout=60
616
+ )
598
617
  success("Synced and pushed to remote")
599
618
  except subprocess.CalledProcessError:
600
619
  success("Synced locally (no remote configured)")
@@ -614,7 +633,11 @@ def store_status():
614
633
 
615
634
  # Git status
616
635
  result = subprocess.run(
617
- ["git", "status", "--short", "--branch"], cwd=store_path, capture_output=True, text=True
636
+ ["git", "status", "--short", "--branch"],
637
+ cwd=store_path,
638
+ capture_output=True,
639
+ text=True,
640
+ timeout=60,
618
641
  )
619
642
 
620
643
  if result.stdout:
@@ -622,7 +645,7 @@ def store_status():
622
645
 
623
646
  # Show remote
624
647
  result = subprocess.run(
625
- ["git", "remote", "-v"], cwd=store_path, capture_output=True, text=True
648
+ ["git", "remote", "-v"], cwd=store_path, capture_output=True, text=True, timeout=60
626
649
  )
627
650
 
628
651
  if result.stdout:
@@ -656,17 +679,23 @@ def configure_store(remote, path):
656
679
  if remote:
657
680
  # Check if remote exists
658
681
  result = subprocess.run(
659
- ["git", "remote"], cwd=store_path, capture_output=True, text=True
682
+ ["git", "remote"], cwd=store_path, capture_output=True, text=True, timeout=60
660
683
  )
661
684
 
662
685
  if "origin" in result.stdout:
663
686
  subprocess.run(
664
- ["git", "remote", "set-url", "origin", remote], cwd=store_path, check=True
687
+ ["git", "remote", "set-url", "origin", remote],
688
+ cwd=store_path,
689
+ check=True,
690
+ timeout=60,
665
691
  )
666
692
  success(f"Updated remote URL: {remote}")
667
693
  else:
668
694
  subprocess.run(
669
- ["git", "remote", "add", "origin", remote], cwd=store_path, check=True
695
+ ["git", "remote", "add", "origin", remote],
696
+ cwd=store_path,
697
+ check=True,
698
+ timeout=60,
670
699
  )
671
700
  success(f"Added remote URL: {remote}")
672
701
 
@@ -1391,9 +1420,7 @@ def add_command(command_name, group, description, template, language, shell, is_
1391
1420
  if language != "ipynb":
1392
1421
  import stat
1393
1422
 
1394
- script_path.chmod(
1395
- script_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
1396
- )
1423
+ script_path.chmod(script_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP)
1397
1424
 
1398
1425
  logger.info(f"Created script: {script_path}")
1399
1426
  except Exception as e:
@@ -11,6 +11,7 @@ from mcli.lib.logger.logger import disable_runtime_tracing, enable_runtime_traci
11
11
 
12
12
  # Desired command order for help display
13
13
  COMMAND_ORDER = [
14
+ "setup",
14
15
  "init",
15
16
  "new",
16
17
  "import",
@@ -20,6 +21,7 @@ COMMAND_ORDER = [
20
21
  "search",
21
22
  "list",
22
23
  "run",
24
+ "source",
23
25
  "context",
24
26
  "health",
25
27
  "services",
@@ -110,6 +112,10 @@ def discover_modules(base_path: Path, config_path: Optional[Path] = None) -> lis
110
112
  config = tomli.load(f)
111
113
  logger.debug(f"Config loaded: {config}")
112
114
  logger.debug(f"Using config from {config_path}")
115
+ KNOWN_CONFIG_KEYS = {"paths", "settings", "plugins", "commands", "services"}
116
+ unknown_keys = set(config.keys()) - KNOWN_CONFIG_KEYS
117
+ if unknown_keys:
118
+ logger.warning(f"Unknown keys in config.toml: {unknown_keys}. Check for typos.")
113
119
  except Exception as e:
114
120
  logger.warning(f"Error reading config file {config_path}: {e}")
115
121
  config = {"paths": {"included_dirs": ["app", "self", "workflow", "public"]}}
@@ -441,6 +447,15 @@ def _add_lazy_commands(app: click.Group):
441
447
  except ImportError as e:
442
448
  logger.debug(f"Could not load sync group: {e}")
443
449
 
450
+ # mcli setup - Onboarding wizard for new users
451
+ try:
452
+ from mcli.app.setup_cmd import setup
453
+
454
+ app.add_command(setup, name="setup")
455
+ logger.debug("Added setup command")
456
+ except ImportError as e:
457
+ logger.debug(f"Could not load setup command: {e}")
458
+
444
459
  # mcli init - Top-level shortcut to initialize workflows directory
445
460
  try:
446
461
  from mcli.app.init_cmd import init
@@ -468,6 +483,15 @@ def _add_lazy_commands(app: click.Group):
468
483
  except ImportError as e:
469
484
  logger.debug(f"Could not load health command: {e}")
470
485
 
486
+ # mcli source - Python source file sync
487
+ try:
488
+ from mcli.app.source_sync_cmd import source_group
489
+
490
+ app.add_command(source_group, name="source")
491
+ logger.debug("Added source sync command")
492
+ except ImportError as e:
493
+ logger.debug(f"Could not load source sync command: {e}")
494
+
471
495
  # mcli services - Service lifecycle management
472
496
  try:
473
497
  from mcli.app.services_cmd import services
@@ -5,10 +5,8 @@ This stub exists for backwards compatibility with tests and imports.
5
5
  The actual model command implementation is now in ~/.mcli/workflows/model.json
6
6
  """
7
7
 
8
- import json
9
8
  import sys
10
9
  from pathlib import Path
11
- from typing import Any
12
10
 
13
11
  from mcli.lib.constants.paths import DirNames
14
12
 
@@ -21,38 +19,16 @@ try:
21
19
  model_json_path = Path.home() / DirNames.MCLI / "commands" / "model.json"
22
20
 
23
21
  if model_json_path.exists():
24
- # Load the command from the JSON file
25
- with open(model_json_path) as f:
26
- command_data = json.load(f)
27
-
28
- # Execute the code to get the app (model command group)
29
- code = command_data.get("code", "")
30
- namespace: dict[str, Any] = {}
31
- exec(code, namespace)
32
-
33
- # Extract the app (model command group) and individual commands
34
- app = namespace.get("app")
35
- if app:
36
- # The model group command
37
- model = app
38
-
39
- # Extract individual subcommands from the model group
40
- if hasattr(model, "commands"):
41
- commands = model.commands
42
- list = commands.get("list")
43
- download = commands.get("download")
44
- start = commands.get("start")
45
- recommend = commands.get("recommend")
46
- status = commands.get("status")
47
- stop = commands.get("stop")
48
- pull = commands.get("pull")
49
- delete = commands.get("delete")
50
- else:
51
- # Fallback if commands aren't available
52
- list = download = start = recommend = status = stop = pull = delete = None
53
- else:
54
- # If app is not found, create empty placeholders
55
- model = list = download = start = recommend = status = stop = pull = delete = None
22
+ # SECURITY: Do not execute arbitrary code from JSON files (fixes #165)
23
+ # The model command should be registered through the workflow system instead
24
+ import logging
25
+
26
+ _logger = logging.getLogger(__name__)
27
+ _logger.warning(
28
+ "model.json contains executable code - skipping exec() for security. "
29
+ "Use workflow system instead."
30
+ )
31
+ model = list = download = start = recommend = status = stop = pull = delete = None
56
32
  else:
57
33
  # If the JSON file doesn't exist, create empty placeholders
58
34
  print(f"Warning: {model_json_path} not found", file=sys.stderr)
@@ -696,9 +696,9 @@ def save_script(
696
696
  with open(script_path, "w") as f:
697
697
  f.write(code)
698
698
 
699
- # Make executable for shell/python scripts
699
+ # Make executable for shell/python scripts (owner + group, not world)
700
700
  if language in (ScriptLanguages.PYTHON, ScriptLanguages.SHELL):
701
- script_path.chmod(script_path.stat().st_mode | stat.S_IXUSR)
701
+ script_path.chmod(script_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP)
702
702
 
703
703
  return script_path
704
704
 
@@ -0,0 +1,187 @@
1
+ """
2
+ Onboarding wizard for new MCLI users.
3
+
4
+ Provides interactive and non-interactive setup modes to configure
5
+ MCLI with validated settings.
6
+ """
7
+
8
+ import os
9
+ from pathlib import Path
10
+
11
+ import click
12
+ from rich.prompt import Confirm, Prompt
13
+ from rich.table import Table
14
+
15
+ from mcli.lib.logger.logger import get_logger
16
+ from mcli.lib.ui.styling import console, info, success
17
+
18
+ logger = get_logger(__name__)
19
+
20
+
21
+ def _write_env_file(env_dict: dict, path: Path):
22
+ """Write a validated env dict to a .env file, preserving existing keys."""
23
+ existing = {}
24
+ if path.exists():
25
+ for line in path.read_text().splitlines():
26
+ line = line.strip()
27
+ if line and not line.startswith("#") and "=" in line:
28
+ key, _, val = line.partition("=")
29
+ existing[key.strip()] = val.strip()
30
+
31
+ merged = {**existing, **env_dict}
32
+
33
+ lines = ["# MCLI Configuration (generated by mcli setup)", ""]
34
+ for key in sorted(merged):
35
+ lines.append(f"{key}={merged[key]}")
36
+ lines.append("")
37
+
38
+ path.write_text("\n".join(lines))
39
+
40
+
41
+ def _write_config_toml(included_dirs: list, path: Path):
42
+ """Write a config.toml with paths configuration."""
43
+ dirs_str = ", ".join(f'"{d}"' for d in included_dirs)
44
+ content = f"""# MCLI Configuration
45
+ # Generated by mcli setup
46
+
47
+ [paths]
48
+ included_dirs = [{dirs_str}]
49
+ """
50
+ path.write_text(content)
51
+
52
+
53
+ def _run_minimal_setup():
54
+ """Minimal setup: just create directories and default config."""
55
+ from mcli.lib.config.settings import MCLISettings
56
+
57
+ settings = MCLISettings()
58
+ home = settings.home_path
59
+ home.mkdir(parents=True, exist_ok=True)
60
+ (home / "workflows").mkdir(exist_ok=True)
61
+
62
+ config_toml = home / "config.toml"
63
+ if not config_toml.exists():
64
+ _write_config_toml(settings.included_dirs, config_toml)
65
+
66
+ return settings
67
+
68
+
69
+ def _run_interactive_setup():
70
+ """Interactive setup: ask user for configuration choices."""
71
+ from mcli.lib.config.settings import MCLISettings
72
+
73
+ console.print()
74
+ console.print("[bold cyan]MCLI Setup Wizard[/bold cyan]")
75
+ console.print("[dim]Configure your MCLI installation step by step.[/dim]")
76
+ console.print()
77
+
78
+ env_overrides = {}
79
+
80
+ # Step 1: Environment
81
+ env = Prompt.ask(
82
+ "[cyan]Environment[/cyan]",
83
+ choices=["development", "staging", "production"],
84
+ default="development",
85
+ )
86
+ if env != "development":
87
+ env_overrides["MCLI_ENV"] = env
88
+
89
+ # Step 2: Editor
90
+ default_editor = os.getenv("EDITOR", "vim")
91
+ editor = Prompt.ask("[cyan]Preferred editor[/cyan]", default=default_editor)
92
+ if editor != "vim":
93
+ env_overrides["EDITOR"] = editor
94
+
95
+ # Step 3: API keys (optional)
96
+ console.print()
97
+ console.print("[bold]API Keys[/bold] [dim](optional, press Enter to skip)[/dim]")
98
+
99
+ openai_key = Prompt.ask("[cyan]OpenAI API key[/cyan]", default="", show_default=False)
100
+ if openai_key:
101
+ env_overrides["OPENAI_API_KEY"] = openai_key
102
+
103
+ anthropic_key = Prompt.ask("[cyan]Anthropic API key[/cyan]", default="", show_default=False)
104
+ if anthropic_key:
105
+ env_overrides["ANTHROPIC_API_KEY"] = anthropic_key
106
+
107
+ # Step 4: Debug mode
108
+ console.print()
109
+ if Confirm.ask("[cyan]Enable debug mode?[/cyan]", default=False):
110
+ env_overrides["MCLI_DEBUG"] = "1"
111
+
112
+ # Build validated settings
113
+ settings = MCLISettings(**env_overrides, _env_file=None)
114
+
115
+ # Create directories
116
+ home = settings.home_path
117
+ home.mkdir(parents=True, exist_ok=True)
118
+ (home / "workflows").mkdir(exist_ok=True)
119
+
120
+ # Write config files
121
+ env_dict = settings.to_env_dict()
122
+ env_dict.update({k: v for k, v in env_overrides.items() if k not in env_dict and v})
123
+
124
+ if env_dict:
125
+ env_path = Path.cwd() / ".env"
126
+ _write_env_file(env_dict, env_path)
127
+ console.print(f"[green]\u2713[/green] Wrote .env to {env_path}")
128
+
129
+ config_toml = home / "config.toml"
130
+ if not config_toml.exists():
131
+ _write_config_toml(settings.included_dirs, config_toml)
132
+ console.print(f"[green]\u2713[/green] Wrote config.toml to {config_toml}")
133
+
134
+ return settings
135
+
136
+
137
+ @click.command("setup")
138
+ @click.option("--minimal", is_flag=True, help="Minimal setup (directories + defaults only)")
139
+ @click.option("--full", is_flag=True, help="Full setup with all optional features")
140
+ def setup(minimal, full):
141
+ """Interactive setup wizard for new users.
142
+
143
+ Configures MCLI with validated settings, creates necessary directories,
144
+ and writes configuration files.
145
+
146
+ Examples:
147
+ mcli setup # Interactive wizard
148
+ mcli setup --minimal # Directories + defaults only
149
+ mcli setup --full # All features configured
150
+ """
151
+ from mcli.lib.config.settings import MCLISettings
152
+
153
+ if minimal:
154
+ settings = _run_minimal_setup()
155
+ success("Minimal setup complete!")
156
+ elif full:
157
+ # Full mode: same as interactive but with all prompts
158
+ settings = _run_interactive_setup()
159
+ else:
160
+ settings = _run_interactive_setup()
161
+
162
+ # Summary table
163
+ console.print()
164
+ table = Table(title="Setup Summary", show_header=False)
165
+ table.add_column("Setting", style="cyan")
166
+ table.add_column("Value", style="green")
167
+
168
+ table.add_row("Environment", settings.mcli_env)
169
+ table.add_row("Home Directory", str(settings.home_path))
170
+ table.add_row("Workflows", str(settings.workflows_dir))
171
+ table.add_row("Editor", settings.editor)
172
+ table.add_row("Debug Mode", "Yes" if settings.is_debug else "No")
173
+ table.add_row("OpenAI API", "Configured" if settings.has_api_key("openai") else "Not set")
174
+ table.add_row(
175
+ "Anthropic API",
176
+ "Configured" if settings.has_api_key("anthropic") else "Not set",
177
+ )
178
+
179
+ console.print(table)
180
+ console.print()
181
+
182
+ # Next steps
183
+ console.print("[bold]Next Steps:[/bold]")
184
+ console.print(" 1. Initialize workflows: [cyan]mcli init[/cyan]")
185
+ console.print(" 2. Create a command: [cyan]mcli new my-command[/cyan]")
186
+ console.print(" 3. Run a command: [cyan]mcli run my-command[/cyan]")
187
+ console.print()