mcli-framework 7.8.4__py3-none-any.whl → 7.9.0__py3-none-any.whl
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.
Potentially problematic release.
This version of mcli-framework might be problematic. Click here for more details.
- mcli/__init__.py +160 -0
- mcli/__main__.py +14 -0
- mcli/app/__init__.py +23 -0
- mcli/app/main.py +10 -17
- mcli/app/model/__init__.py +0 -0
- mcli/app/model_cmd.py +57 -472
- mcli/app/video/__init__.py +5 -0
- mcli/chat/__init__.py +34 -0
- mcli/lib/__init__.py +0 -0
- mcli/lib/api/__init__.py +0 -0
- mcli/lib/auth/__init__.py +1 -0
- mcli/lib/config/__init__.py +1 -0
- mcli/lib/erd/__init__.py +25 -0
- mcli/lib/files/__init__.py +0 -0
- mcli/lib/fs/__init__.py +1 -0
- mcli/lib/lib.py +8 -1
- mcli/lib/logger/__init__.py +3 -0
- mcli/lib/performance/__init__.py +17 -0
- mcli/lib/pickles/__init__.py +1 -0
- mcli/lib/secrets/__init__.py +10 -0
- mcli/lib/secrets/commands.py +185 -0
- mcli/lib/secrets/manager.py +213 -0
- mcli/lib/secrets/repl.py +297 -0
- mcli/lib/secrets/store.py +246 -0
- mcli/lib/shell/__init__.py +0 -0
- mcli/lib/toml/__init__.py +1 -0
- mcli/lib/watcher/__init__.py +0 -0
- mcli/ml/__init__.py +16 -0
- mcli/ml/api/__init__.py +30 -0
- mcli/ml/api/routers/__init__.py +27 -0
- mcli/ml/auth/__init__.py +41 -0
- mcli/ml/backtesting/__init__.py +33 -0
- mcli/ml/cli/__init__.py +5 -0
- mcli/ml/config/__init__.py +33 -0
- mcli/ml/configs/__init__.py +16 -0
- mcli/ml/dashboard/__init__.py +12 -0
- mcli/ml/dashboard/components/__init__.py +7 -0
- mcli/ml/dashboard/pages/__init__.py +6 -0
- mcli/ml/data_ingestion/__init__.py +29 -0
- mcli/ml/database/__init__.py +40 -0
- mcli/ml/experimentation/__init__.py +29 -0
- mcli/ml/features/__init__.py +39 -0
- mcli/ml/mlops/__init__.py +19 -0
- mcli/ml/models/__init__.py +90 -0
- mcli/ml/monitoring/__init__.py +25 -0
- mcli/ml/optimization/__init__.py +27 -0
- mcli/ml/predictions/__init__.py +5 -0
- mcli/ml/preprocessing/__init__.py +24 -0
- mcli/ml/scripts/__init__.py +1 -0
- mcli/ml/trading/__init__.py +63 -0
- mcli/ml/training/__init__.py +7 -0
- mcli/mygroup/__init__.py +3 -0
- mcli/public/__init__.py +1 -0
- mcli/public/commands/__init__.py +2 -0
- mcli/self/__init__.py +3 -0
- mcli/self/self_cmd.py +8 -0
- mcli/self/zsh_cmd.py +259 -0
- mcli/workflow/__init__.py +0 -0
- mcli/workflow/daemon/__init__.py +15 -0
- mcli/workflow/dashboard/__init__.py +5 -0
- mcli/workflow/docker/__init__.py +0 -0
- mcli/workflow/file/__init__.py +0 -0
- mcli/workflow/gcloud/__init__.py +1 -0
- mcli/workflow/git_commit/__init__.py +0 -0
- mcli/workflow/interview/__init__.py +0 -0
- mcli/workflow/politician_trading/__init__.py +4 -0
- mcli/workflow/registry/__init__.py +0 -0
- mcli/workflow/repo/__init__.py +0 -0
- mcli/workflow/scheduler/__init__.py +25 -0
- mcli/workflow/search/__init__.py +0 -0
- mcli/workflow/sync/__init__.py +5 -0
- mcli/workflow/videos/__init__.py +1 -0
- mcli/workflow/wakatime/__init__.py +80 -0
- {mcli_framework-7.8.4.dist-info → mcli_framework-7.9.0.dist-info}/METADATA +2 -1
- {mcli_framework-7.8.4.dist-info → mcli_framework-7.9.0.dist-info}/RECORD +79 -12
- mcli/app/chat_cmd.py +0 -42
- mcli/test/test_cmd.py +0 -20
- {mcli_framework-7.8.4.dist-info → mcli_framework-7.9.0.dist-info}/WHEEL +0 -0
- {mcli_framework-7.8.4.dist-info → mcli_framework-7.9.0.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.8.4.dist-info → mcli_framework-7.9.0.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.8.4.dist-info → mcli_framework-7.9.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""ML Models for Stock Recommendation System"""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Dict, Optional
|
|
5
|
+
|
|
6
|
+
import torch
|
|
7
|
+
|
|
8
|
+
from .base_models import BaseStockModel, ModelMetrics, ValidationResult
|
|
9
|
+
from .ensemble_models import (
|
|
10
|
+
AttentionStockPredictor,
|
|
11
|
+
CNNFeatureExtractor,
|
|
12
|
+
DeepEnsembleModel,
|
|
13
|
+
EnsembleConfig,
|
|
14
|
+
EnsembleTrainer,
|
|
15
|
+
LSTMStockPredictor,
|
|
16
|
+
ModelConfig,
|
|
17
|
+
TransformerStockModel,
|
|
18
|
+
)
|
|
19
|
+
from .recommendation_models import (
|
|
20
|
+
RecommendationConfig,
|
|
21
|
+
RecommendationTrainer,
|
|
22
|
+
StockRecommendationModel,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Model registry
|
|
26
|
+
_loaded_models: Dict[str, Any] = {}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def load_production_models():
|
|
30
|
+
"""Load production models into memory"""
|
|
31
|
+
from mcli.ml.config import settings
|
|
32
|
+
from mcli.ml.logging import get_logger
|
|
33
|
+
|
|
34
|
+
logger = get_logger(__name__)
|
|
35
|
+
model_dir = settings.model.model_dir
|
|
36
|
+
|
|
37
|
+
if not model_dir.exists():
|
|
38
|
+
model_dir.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
for model_path in model_dir.glob("*.pt"):
|
|
42
|
+
try:
|
|
43
|
+
model_id = model_path.stem
|
|
44
|
+
model = torch.load(model_path, map_location=settings.model.device)
|
|
45
|
+
_loaded_models[model_id] = model
|
|
46
|
+
logger.info(f"Loaded model: {model_id}")
|
|
47
|
+
except Exception as e:
|
|
48
|
+
logger.error(f"Failed to load model {model_path}: {e}")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async def get_model_by_id(model_id: str):
|
|
52
|
+
"""Get loaded model by ID"""
|
|
53
|
+
from mcli.ml.config import settings
|
|
54
|
+
|
|
55
|
+
if model_id not in _loaded_models:
|
|
56
|
+
# Try to load from disk
|
|
57
|
+
model_path = settings.model.model_dir / f"{model_id}.pt"
|
|
58
|
+
if model_path.exists():
|
|
59
|
+
_loaded_models[model_id] = torch.load(model_path, map_location=settings.model.device)
|
|
60
|
+
|
|
61
|
+
return _loaded_models.get(model_id)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def initialize_models():
|
|
65
|
+
"""Initialize models on startup"""
|
|
66
|
+
from mcli.ml.logging import get_logger
|
|
67
|
+
|
|
68
|
+
logger = get_logger(__name__)
|
|
69
|
+
logger.info("Initializing ML models...")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__all__ = [
|
|
73
|
+
"DeepEnsembleModel",
|
|
74
|
+
"AttentionStockPredictor",
|
|
75
|
+
"TransformerStockModel",
|
|
76
|
+
"LSTMStockPredictor",
|
|
77
|
+
"CNNFeatureExtractor",
|
|
78
|
+
"EnsembleTrainer",
|
|
79
|
+
"ModelConfig",
|
|
80
|
+
"EnsembleConfig",
|
|
81
|
+
"BaseStockModel",
|
|
82
|
+
"ModelMetrics",
|
|
83
|
+
"ValidationResult",
|
|
84
|
+
"StockRecommendationModel",
|
|
85
|
+
"RecommendationTrainer",
|
|
86
|
+
"RecommendationConfig",
|
|
87
|
+
"load_production_models",
|
|
88
|
+
"get_model_by_id",
|
|
89
|
+
"initialize_models",
|
|
90
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""ML Model Monitoring and Drift Detection"""
|
|
2
|
+
|
|
3
|
+
from .drift_detection import (
|
|
4
|
+
AlertSeverity,
|
|
5
|
+
ConceptDriftDetector,
|
|
6
|
+
DataProfile,
|
|
7
|
+
DriftAlert,
|
|
8
|
+
DriftType,
|
|
9
|
+
ModelMetrics,
|
|
10
|
+
ModelMonitor,
|
|
11
|
+
OutlierDetector,
|
|
12
|
+
StatisticalDriftDetector,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"ModelMonitor",
|
|
17
|
+
"StatisticalDriftDetector",
|
|
18
|
+
"ConceptDriftDetector",
|
|
19
|
+
"OutlierDetector",
|
|
20
|
+
"DriftAlert",
|
|
21
|
+
"DriftType",
|
|
22
|
+
"AlertSeverity",
|
|
23
|
+
"ModelMetrics",
|
|
24
|
+
"DataProfile",
|
|
25
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Advanced Portfolio Optimization"""
|
|
2
|
+
|
|
3
|
+
from .portfolio_optimizer import (
|
|
4
|
+
AdvancedPortfolioOptimizer,
|
|
5
|
+
BaseOptimizer,
|
|
6
|
+
BlackLittermanOptimizer,
|
|
7
|
+
CVaROptimizer,
|
|
8
|
+
KellyCriterionOptimizer,
|
|
9
|
+
MeanVarianceOptimizer,
|
|
10
|
+
OptimizationConstraints,
|
|
11
|
+
OptimizationObjective,
|
|
12
|
+
PortfolioAllocation,
|
|
13
|
+
RiskParityOptimizer,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"AdvancedPortfolioOptimizer",
|
|
18
|
+
"OptimizationObjective",
|
|
19
|
+
"OptimizationConstraints",
|
|
20
|
+
"PortfolioAllocation",
|
|
21
|
+
"MeanVarianceOptimizer",
|
|
22
|
+
"RiskParityOptimizer",
|
|
23
|
+
"BlackLittermanOptimizer",
|
|
24
|
+
"CVaROptimizer",
|
|
25
|
+
"KellyCriterionOptimizer",
|
|
26
|
+
"BaseOptimizer",
|
|
27
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""ML Data Preprocessing Module"""
|
|
2
|
+
|
|
3
|
+
from .data_cleaners import MissingValueHandler, OutlierDetector, TradingDataCleaner
|
|
4
|
+
from .feature_extractors import (
|
|
5
|
+
MarketFeatureExtractor,
|
|
6
|
+
PoliticianFeatureExtractor,
|
|
7
|
+
SentimentFeatureExtractor,
|
|
8
|
+
TemporalFeatureExtractor,
|
|
9
|
+
)
|
|
10
|
+
from .ml_pipeline import MLDataPipeline, MLDataPipelineConfig
|
|
11
|
+
from .politician_trading_preprocessor import PoliticianTradingPreprocessor
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"PoliticianTradingPreprocessor",
|
|
15
|
+
"PoliticianFeatureExtractor",
|
|
16
|
+
"MarketFeatureExtractor",
|
|
17
|
+
"TemporalFeatureExtractor",
|
|
18
|
+
"SentimentFeatureExtractor",
|
|
19
|
+
"TradingDataCleaner",
|
|
20
|
+
"OutlierDetector",
|
|
21
|
+
"MissingValueHandler",
|
|
22
|
+
"MLDataPipeline",
|
|
23
|
+
"MLDataPipelineConfig",
|
|
24
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""ML scripts module."""
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Trading module for portfolio management and trade execution"""
|
|
2
|
+
|
|
3
|
+
from mcli.ml.trading.alpaca_client import (
|
|
4
|
+
AlpacaTradingClient,
|
|
5
|
+
create_trading_client,
|
|
6
|
+
get_alpaca_config_from_env,
|
|
7
|
+
)
|
|
8
|
+
from mcli.ml.trading.models import ( # Enums; Database models; Pydantic models
|
|
9
|
+
OrderCreate,
|
|
10
|
+
OrderResponse,
|
|
11
|
+
OrderSide,
|
|
12
|
+
OrderStatus,
|
|
13
|
+
OrderType,
|
|
14
|
+
Portfolio,
|
|
15
|
+
PortfolioCreate,
|
|
16
|
+
PortfolioPerformanceSnapshot,
|
|
17
|
+
PortfolioResponse,
|
|
18
|
+
PortfolioType,
|
|
19
|
+
Position,
|
|
20
|
+
PositionResponse,
|
|
21
|
+
PositionSide,
|
|
22
|
+
RiskLevel,
|
|
23
|
+
TradingAccount,
|
|
24
|
+
TradingAccountCreate,
|
|
25
|
+
TradingOrder,
|
|
26
|
+
TradingSignal,
|
|
27
|
+
TradingSignalResponse,
|
|
28
|
+
)
|
|
29
|
+
from mcli.ml.trading.paper_trading import PaperTradingEngine
|
|
30
|
+
from mcli.ml.trading.risk_management import RiskManager
|
|
31
|
+
from mcli.ml.trading.trading_service import TradingService
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
# Enums
|
|
35
|
+
"OrderStatus",
|
|
36
|
+
"OrderType",
|
|
37
|
+
"OrderSide",
|
|
38
|
+
"PositionSide",
|
|
39
|
+
"PortfolioType",
|
|
40
|
+
"RiskLevel",
|
|
41
|
+
# Database models
|
|
42
|
+
"TradingAccount",
|
|
43
|
+
"Portfolio",
|
|
44
|
+
"Position",
|
|
45
|
+
"TradingOrder",
|
|
46
|
+
"PortfolioPerformanceSnapshot",
|
|
47
|
+
"TradingSignal",
|
|
48
|
+
# Pydantic models
|
|
49
|
+
"TradingAccountCreate",
|
|
50
|
+
"PortfolioCreate",
|
|
51
|
+
"OrderCreate",
|
|
52
|
+
"PositionResponse",
|
|
53
|
+
"OrderResponse",
|
|
54
|
+
"PortfolioResponse",
|
|
55
|
+
"TradingSignalResponse",
|
|
56
|
+
# Services
|
|
57
|
+
"TradingService",
|
|
58
|
+
"AlpacaTradingClient",
|
|
59
|
+
"create_trading_client",
|
|
60
|
+
"get_alpaca_config_from_env",
|
|
61
|
+
"RiskManager",
|
|
62
|
+
"PaperTradingEngine",
|
|
63
|
+
]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""ML model training module"""
|
|
2
|
+
|
|
3
|
+
from .train_model import PoliticianTradingNet, fetch_training_data
|
|
4
|
+
from .train_model import main as train_model
|
|
5
|
+
from .train_model import prepare_dataset
|
|
6
|
+
|
|
7
|
+
__all__ = ["PoliticianTradingNet", "train_model", "fetch_training_data", "prepare_dataset"]
|
mcli/mygroup/__init__.py
ADDED
mcli/public/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# logger.info("I am in mcli.public.__init__.py")
|
mcli/self/__init__.py
ADDED
mcli/self/self_cmd.py
CHANGED
|
@@ -1029,6 +1029,14 @@ try:
|
|
|
1029
1029
|
except ImportError as e:
|
|
1030
1030
|
logger.debug(f"Could not load redis command: {e}")
|
|
1031
1031
|
|
|
1032
|
+
try:
|
|
1033
|
+
from mcli.self.zsh_cmd import zsh_group
|
|
1034
|
+
|
|
1035
|
+
self_app.add_command(zsh_group, name="zsh")
|
|
1036
|
+
logger.debug("Added zsh command to self group")
|
|
1037
|
+
except ImportError as e:
|
|
1038
|
+
logger.debug(f"Could not load zsh command: {e}")
|
|
1039
|
+
|
|
1032
1040
|
try:
|
|
1033
1041
|
from mcli.self.visual_cmd import visual
|
|
1034
1042
|
|
mcli/self/zsh_cmd.py
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ZSH-specific commands and utilities for MCLI.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
|
|
12
|
+
from mcli.lib.logger.logger import get_logger
|
|
13
|
+
|
|
14
|
+
logger = get_logger(__name__)
|
|
15
|
+
from mcli.lib.ui.styling import error, info, success, warning
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.group(name="zsh", help="ZSH shell integration and utilities")
|
|
19
|
+
def zsh_group():
|
|
20
|
+
"""ZSH-specific commands and utilities."""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@zsh_group.command(name="config", help="Configure ZSH for optimal MCLI experience")
|
|
25
|
+
@click.option("--force", is_flag=True, help="Force reconfiguration even if already set up")
|
|
26
|
+
def zsh_config(force: bool):
|
|
27
|
+
"""Configure ZSH with MCLI-specific settings."""
|
|
28
|
+
zshrc = Path.home() / ".zshrc"
|
|
29
|
+
|
|
30
|
+
if not zshrc.exists():
|
|
31
|
+
if click.confirm("No .zshrc found. Create one?"):
|
|
32
|
+
zshrc.touch()
|
|
33
|
+
else:
|
|
34
|
+
warning("Configuration cancelled")
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
configs_added = [] # noqa: F841
|
|
38
|
+
|
|
39
|
+
# Read existing content
|
|
40
|
+
content = zshrc.read_text()
|
|
41
|
+
|
|
42
|
+
# MCLI configuration block
|
|
43
|
+
mcli_block_start = "# BEGIN MCLI ZSH CONFIG"
|
|
44
|
+
mcli_block_end = "# END MCLI ZSH CONFIG"
|
|
45
|
+
|
|
46
|
+
if mcli_block_start in content and not force:
|
|
47
|
+
info("MCLI ZSH configuration already exists. Use --force to reconfigure.")
|
|
48
|
+
return
|
|
49
|
+
|
|
50
|
+
# Remove old block if forcing
|
|
51
|
+
if mcli_block_start in content and force:
|
|
52
|
+
lines = content.split("\n")
|
|
53
|
+
new_lines = []
|
|
54
|
+
in_block = False
|
|
55
|
+
|
|
56
|
+
for line in lines:
|
|
57
|
+
if line.strip() == mcli_block_start:
|
|
58
|
+
in_block = True
|
|
59
|
+
elif line.strip() == mcli_block_end:
|
|
60
|
+
in_block = False
|
|
61
|
+
continue
|
|
62
|
+
elif not in_block:
|
|
63
|
+
new_lines.append(line)
|
|
64
|
+
|
|
65
|
+
content = "\n".join(new_lines)
|
|
66
|
+
|
|
67
|
+
# Build configuration
|
|
68
|
+
config_lines = [
|
|
69
|
+
"",
|
|
70
|
+
mcli_block_start,
|
|
71
|
+
"# MCLI aliases",
|
|
72
|
+
"alias m='mcli'",
|
|
73
|
+
"alias mc='mcli chat'",
|
|
74
|
+
"alias mw='mcli workflow'",
|
|
75
|
+
"alias ms='mcli self'",
|
|
76
|
+
"alias mls='mcli lib secrets'",
|
|
77
|
+
"alias mlsr='mcli lib secrets repl'",
|
|
78
|
+
"",
|
|
79
|
+
"# MCLI environment",
|
|
80
|
+
'export MCLI_HOME="$HOME/.mcli"',
|
|
81
|
+
'export PATH="$MCLI_HOME/bin:$PATH"',
|
|
82
|
+
"",
|
|
83
|
+
"# MCLI completion",
|
|
84
|
+
'fpath=("$HOME/.config/zsh/completions" $fpath)',
|
|
85
|
+
"autoload -U compinit && compinit",
|
|
86
|
+
"",
|
|
87
|
+
"# MCLI prompt integration (optional)",
|
|
88
|
+
'# PS1="%{$fg[cyan]%}[mcli]%{$reset_color%} $PS1"',
|
|
89
|
+
"",
|
|
90
|
+
mcli_block_end,
|
|
91
|
+
"",
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
# Append configuration
|
|
95
|
+
with zshrc.open("a") as f:
|
|
96
|
+
f.write("\n".join(config_lines))
|
|
97
|
+
|
|
98
|
+
success("ZSH configuration added successfully!")
|
|
99
|
+
|
|
100
|
+
# Install completion if not already installed
|
|
101
|
+
completion_dir = Path.home() / ".config" / "zsh" / "completions"
|
|
102
|
+
completion_file = completion_dir / "_mcli"
|
|
103
|
+
|
|
104
|
+
if not completion_file.exists():
|
|
105
|
+
info("Installing ZSH completion...")
|
|
106
|
+
try:
|
|
107
|
+
subprocess.run(["mcli", "self", "completion", "install", "--shell=zsh"], check=True)
|
|
108
|
+
configs_added.append("completion")
|
|
109
|
+
except subprocess.CalledProcessError:
|
|
110
|
+
warning("Failed to install completion automatically")
|
|
111
|
+
|
|
112
|
+
info("\nConfigured:")
|
|
113
|
+
info(" • Aliases: m, mc, mw, ms, mls, mlsr")
|
|
114
|
+
info(" • Environment variables: MCLI_HOME, PATH")
|
|
115
|
+
info(" • Shell completion support")
|
|
116
|
+
info("\nReload your shell configuration:")
|
|
117
|
+
info(" source ~/.zshrc")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@zsh_group.command(name="aliases", help="Show available ZSH aliases")
|
|
121
|
+
def zsh_aliases():
|
|
122
|
+
"""Display MCLI ZSH aliases."""
|
|
123
|
+
aliases = [
|
|
124
|
+
("m", "mcli", "Main MCLI command"),
|
|
125
|
+
("mc", "mcli chat", "Open chat interface"),
|
|
126
|
+
("mw", "mcli workflow", "Workflow commands"),
|
|
127
|
+
("ms", "mcli self", "Self management commands"),
|
|
128
|
+
("mls", "mcli lib secrets", "Secrets management"),
|
|
129
|
+
("mlsr", "mcli lib secrets repl", "Secrets REPL"),
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
info("MCLI ZSH Aliases:")
|
|
133
|
+
for alias, command, desc in aliases:
|
|
134
|
+
click.echo(f" {alias:<6} → {command:<25} # {desc}")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@zsh_group.command(name="prompt", help="Configure ZSH prompt with MCLI integration")
|
|
138
|
+
@click.option("--style", type=click.Choice(["simple", "powerline", "minimal"]), default="simple")
|
|
139
|
+
def zsh_prompt(style: str):
|
|
140
|
+
"""Add MCLI status to ZSH prompt."""
|
|
141
|
+
zshrc = Path.home() / ".zshrc"
|
|
142
|
+
|
|
143
|
+
if not zshrc.exists():
|
|
144
|
+
error("No .zshrc found")
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
prompt_configs = {
|
|
148
|
+
"simple": 'PS1="%{$fg[cyan]%}[mcli]%{$reset_color%} $PS1"',
|
|
149
|
+
"powerline": 'PS1="%{$fg[cyan]%} mcli %{$reset_color%}$PS1"',
|
|
150
|
+
"minimal": 'PS1="◆ $PS1"',
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
config = prompt_configs[style]
|
|
154
|
+
|
|
155
|
+
# Check if prompt section exists
|
|
156
|
+
content = zshrc.read_text()
|
|
157
|
+
prompt_marker = "# MCLI prompt integration"
|
|
158
|
+
|
|
159
|
+
if prompt_marker in content:
|
|
160
|
+
# Update existing prompt
|
|
161
|
+
lines = content.split("\n")
|
|
162
|
+
for i, line in enumerate(lines):
|
|
163
|
+
if line.strip() == prompt_marker:
|
|
164
|
+
if i + 1 < len(lines) and lines[i + 1].startswith("PS1="):
|
|
165
|
+
lines[i + 1] = config
|
|
166
|
+
content = "\n".join(lines)
|
|
167
|
+
zshrc.write_text(content)
|
|
168
|
+
success(f"Updated prompt to {style} style")
|
|
169
|
+
break
|
|
170
|
+
else:
|
|
171
|
+
warning("MCLI ZSH configuration not found. Run 'mcli self zsh config' first.")
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@zsh_group.command(name="functions", help="Install useful ZSH functions")
|
|
175
|
+
def zsh_functions():
|
|
176
|
+
"""Install MCLI-specific ZSH functions."""
|
|
177
|
+
functions_dir = Path.home() / ".config" / "zsh" / "functions"
|
|
178
|
+
functions_dir.mkdir(parents=True, exist_ok=True)
|
|
179
|
+
|
|
180
|
+
# Create mcli-quick function
|
|
181
|
+
quick_func = functions_dir / "mcli-quick"
|
|
182
|
+
quick_func.write_text(
|
|
183
|
+
"""# Quick MCLI command runner
|
|
184
|
+
mcli-quick() {
|
|
185
|
+
local cmd=$1
|
|
186
|
+
shift
|
|
187
|
+
mcli $cmd "$@" | head -20
|
|
188
|
+
}"""
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Create mcli-fzf function for fuzzy finding
|
|
192
|
+
fzf_func = functions_dir / "mcli-fzf"
|
|
193
|
+
fzf_func.write_text(
|
|
194
|
+
"""# Fuzzy find MCLI commands
|
|
195
|
+
mcli-fzf() {
|
|
196
|
+
local cmd=$(mcli --help | grep -E '^ [a-z]' | awk '{print $1}' | fzf)
|
|
197
|
+
if [[ -n $cmd ]]; then
|
|
198
|
+
print -z "mcli $cmd "
|
|
199
|
+
fi
|
|
200
|
+
}"""
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# Add to zshrc
|
|
204
|
+
zshrc = Path.home() / ".zshrc"
|
|
205
|
+
if zshrc.exists():
|
|
206
|
+
content = zshrc.read_text()
|
|
207
|
+
fpath_line = f'fpath=("{functions_dir}" $fpath)'
|
|
208
|
+
|
|
209
|
+
if str(functions_dir) not in content:
|
|
210
|
+
with zshrc.open("a") as f:
|
|
211
|
+
f.write(f"\n# MCLI ZSH functions\n{fpath_line}\nautoload -U mcli-quick mcli-fzf\n")
|
|
212
|
+
|
|
213
|
+
success("ZSH functions installed:")
|
|
214
|
+
info(" • mcli-quick: Run MCLI commands with truncated output")
|
|
215
|
+
info(" • mcli-fzf: Fuzzy find MCLI commands (requires fzf)")
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
@zsh_group.command(name="test", help="Test ZSH integration")
|
|
219
|
+
def zsh_test():
|
|
220
|
+
"""Test ZSH integration and configuration."""
|
|
221
|
+
checks = []
|
|
222
|
+
|
|
223
|
+
# Check if running in ZSH
|
|
224
|
+
shell = os.environ.get("SHELL", "")
|
|
225
|
+
if "zsh" in shell:
|
|
226
|
+
checks.append(("ZSH shell detected", True))
|
|
227
|
+
else:
|
|
228
|
+
checks.append(("ZSH shell detected", False))
|
|
229
|
+
|
|
230
|
+
# Check completion
|
|
231
|
+
completion_file = Path.home() / ".config" / "zsh" / "completions" / "_mcli"
|
|
232
|
+
checks.append(("Completion installed", completion_file.exists()))
|
|
233
|
+
|
|
234
|
+
# Check zshrc
|
|
235
|
+
zshrc = Path.home() / ".zshrc"
|
|
236
|
+
if zshrc.exists():
|
|
237
|
+
content = zshrc.read_text()
|
|
238
|
+
checks.append(("MCLI config in .zshrc", "BEGIN MCLI ZSH CONFIG" in content))
|
|
239
|
+
checks.append(("Completion in fpath", ".config/zsh/completions" in content))
|
|
240
|
+
else:
|
|
241
|
+
checks.append((".zshrc exists", False))
|
|
242
|
+
|
|
243
|
+
# Check aliases
|
|
244
|
+
try:
|
|
245
|
+
result = subprocess.run(["zsh", "-c", "alias | grep mcli"], capture_output=True, text=True)
|
|
246
|
+
checks.append(("Aliases configured", result.returncode == 0))
|
|
247
|
+
except:
|
|
248
|
+
checks.append(("Aliases configured", False))
|
|
249
|
+
|
|
250
|
+
# Display results
|
|
251
|
+
info("ZSH Integration Test Results:")
|
|
252
|
+
for check, passed in checks:
|
|
253
|
+
status = "✅" if passed else "❌"
|
|
254
|
+
click.echo(f" {status} {check}")
|
|
255
|
+
|
|
256
|
+
if all(passed for _, passed in checks):
|
|
257
|
+
success("\nAll checks passed! ZSH integration is working correctly.")
|
|
258
|
+
else:
|
|
259
|
+
warning("\nSome checks failed. Run 'mcli self zsh config' to set up integration.")
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Daemon service for command management and execution.
|
|
3
|
+
|
|
4
|
+
This module provides a background daemon service that can store, manage, and execute
|
|
5
|
+
commands written in various programming languages (Python, Node.js, Lua, Shell).
|
|
6
|
+
Commands are stored in a SQLite database with embeddings for similarity search and
|
|
7
|
+
hierarchical grouping.
|
|
8
|
+
|
|
9
|
+
The daemon CLI commands are now loaded from portable JSON files in ~/.mcli/commands/
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from .daemon import Command, CommandExecutor, DaemonService
|
|
13
|
+
|
|
14
|
+
# Export main components
|
|
15
|
+
__all__ = ["Command", "CommandExecutor", "DaemonService"]
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .gcloud import gcloud
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCLI Scheduler Module
|
|
3
|
+
|
|
4
|
+
A robust cron-like job scheduling system with the following features:
|
|
5
|
+
- Cron expression parsing and job scheduling
|
|
6
|
+
- Job monitoring and persistence across restarts
|
|
7
|
+
- JSON API for frontend integration
|
|
8
|
+
- System automation capabilities
|
|
9
|
+
- Desktop file cleanup and management
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from .cron_parser import CronExpression
|
|
13
|
+
from .job import JobStatus, ScheduledJob
|
|
14
|
+
from .monitor import JobMonitor
|
|
15
|
+
from .persistence import JobStorage
|
|
16
|
+
from .scheduler import JobScheduler
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"JobScheduler",
|
|
20
|
+
"ScheduledJob",
|
|
21
|
+
"JobStatus",
|
|
22
|
+
"CronExpression",
|
|
23
|
+
"JobStorage",
|
|
24
|
+
"JobMonitor",
|
|
25
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Videos workflow module
|