-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.py
More file actions
187 lines (162 loc) · 6.03 KB
/
install.py
File metadata and controls
187 lines (162 loc) · 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import subprocess
import os
import json
import shutil
def ensure_uv():
"""
Ensure that the 'uv' module is installed. If not, install it.
"""
# Run which uv
try:
subprocess.run(['which', 'uv'], check=True)
print("uv is already installed.")
return
except subprocess.CalledProcessError:
print("uv is not installed. Installing...")
# Install uv:
# - macos/linus: curl -LsSf https://astral.sh/uv/install.sh | sh
try:
subprocess.run(['curl', '-LsSf', 'https://astral.sh/uv/install.sh', '|', 'sh'], check=True)
print("uv installed successfully.")
except subprocess.CalledProcessError:
input("Failed to install uv. Please install it manually and click Enter to continue.")
def setup_mcp_dot_json():
"""Copies mcp.json from the __file__ directory to the ~/mcp.json
Replaces:
- '/path/to/uv' with the actual path to uv
- '/path/to/repo/' with the actual path to the repository
- all env's with the actual envs or override by input
"""
if os.path.exists(os.path.expanduser('~/mcp.json')):
with open(os.path.expanduser('~/mcp.json'), 'r') as f:
existing_mcp_json = json.load(f)
else:
existing_mcp_json = {'mcpServers': {}}
with open(os.path.join(os.path.dirname(__file__), 'mcp.json'), 'r') as f:
mcp_json = f.read()
# Replace '/app with the actual path to the repository
repo_path = os.path.dirname(os.path.abspath(__file__))
mcp_json = mcp_json.replace('/app', repo_path)
mcp_data = json.loads(mcp_json)
confirmed_env = {}
for name, config in mcp_data['mcpServers'].items():
print(f"Setting up {name}...")
if 'env' in config:
env = config['env']
existing_env = {}
if name in existing_mcp_json['mcpServers']:
existing_env = existing_mcp_json['mcpServers'][name].get('env', {})
for key, value in existing_env.items():
if key in env:
env[key] = value
for key, value in env.items():
if key in existing_env:
value = existing_env[key]
continue
if key in confirmed_env:
value = confirmed_env[key]
else:
default = os.environ.get(key)
value = input(f"Please enter the value for {key} (default: {default}): ")
if not value:
value = default
confirmed_env[key] = value
env[key] = value
for name, config in existing_mcp_json['mcpServers'].items():
if name not in mcp_data['mcpServers']:
mcp_data['mcpServers'][name] = config
# Write the modified mcp.json to ~/mcp.json
with open(os.path.expanduser('~/mcp.json'), 'w') as f:
json.dump(mcp_data, f, indent=4)
print("mcp.json has been set up in ~/mcp.json.")
def setup_component(relpath):
"""
Setup mcp server:
cd relpath
uv venv
source .venv/bin/activate
uv sync
"""
path = os.path.join(os.path.dirname(__file__), relpath)
os.chdir(path)
if not os.path.exists('.venv'):
subprocess.run(['uv', 'venv'], check=True)
subprocess.run(['uv', 'sync'], check=True)
def setup_frontend():
"""
Setup frontend:
cd frontend
npm install
"""
path = os.path.join(os.path.dirname(__file__), 'automator/ui/frontend')
os.chdir(path)
subprocess.run(['npm', 'install'], check=True)
def get_env_from_mcp_json():
"""
Get the env from mcp.json
"""
with open(os.path.expanduser('~/mcp.json'), 'r') as f:
mcp_json = json.load(f)
env = {}
for name, config in mcp_json['mcpServers'].items():
if 'env' in config:
env.update(config['env'])
# Now write to .env
env_path = os.path.join(os.path.dirname(__file__), '.env')
with open(env_path, 'w') as f:
for key, value in env.items():
f.write(f"{key}={value}\n")
print(f"Environment variables have been written to {env_path}.")
def start_backend():
"""
Start backend:
cd backend
.venv/bin/python -m uvicorn automator.api.main:app --port 8000 &> ../backend.logs (in the background)
"""
path = os.path.join(os.path.dirname(__file__), 'automator/ui')
os.chdir(path)
python_path = os.path.join(path, '.venv', 'bin', 'python')
subprocess.Popen(
[python_path, '-m', 'uvicorn', 'api.main:app', '--port', '8000'],
stdout=open('../backend.logs', 'a'),
stderr=subprocess.STDOUT
)
print("Backend started. Logs are being written to backend.logs.")
def start_frontend():
"""
Start frontend:
cd frontend
npm start &> ../frontend.logs(in the background)
"""
path = os.path.join(os.path.dirname(__file__), 'automator/frontend')
os.chdir(path)
subprocess.Popen(['npm', 'run', 'dev'], stdout=open('../../frontend.logs', 'a'), stderr=subprocess.STDOUT)
print("Frontend started. Logs are being written to frontend.logs.")
print("You can now access the frontend at http://localhost:5173.")
def start_all():
"""
Start all components:
start_backend
start_frontend
"""
start_backend()
start_frontend()
def install_repo():
"""
Installs all components of the repo
"""
ensure_uv()
setup_mcp_dot_json()
os.makedirs(os.path.expanduser('~/.automator/workspaces'), exist_ok=True)
# cp prompts ~/.automator/prompts
shutil.copytree(os.path.join(os.path.dirname(__file__), 'automator/prompts'), os.path.expanduser('~/.automator/prompts'), dirs_exist_ok=True)
setup_component('terminal-mcp')
setup_component('web-mcp')
setup_component('talk-to-model')
setup_component('automator')
setup_frontend()
if input("Do you want to start all components? (y/n): ").lower() == 'y':
start_all()
print("For more examples, checkout examples/ and more_examples/")
if __name__ == "__main__":
install_repo()