-
Notifications
You must be signed in to change notification settings - Fork 74
/
go_cli.py
176 lines (156 loc) · 6.64 KB
/
go_cli.py
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
# Copyright 2023 https://github.com/ShishirPatil/gorilla
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import datetime
import os
import sys
import uuid
import requests
import subprocess
import urllib.parse
import sys
from halo import Halo
import go_questionary
__version__ = "0.0.8" # current version
SERVER_URL = "http://34.135.112.197:8000"
UPDATE_CHECK_FILE = os.path.expanduser("~/.gorilla-cli-last-update-check")
USERID_FILE = os.path.expanduser("~/.gorilla-cli-userid")
ISSUE_URL = f"https://github.com/gorilla-llm/gorilla-cli/issues/new"
WELCOME_TEXT = """🦍 Welcome to Gorilla-CLI! Enhance your Command Line with the power of LLMs!
Simply use `gorilla <your desired operation>` and Gorilla will do the rest. For instance:
gorilla what is the path of my current directory
gorilla list all my GCP instances
Created as a research prototype by UC Berkeley, Gorilla-CLI ensures user control and privacy:
- Commands are executed only with explicit user approval.
- While queries and error (stderr) logs are used to refine our model, we NEVER gather output (stdout) data.
Visit us at github.com/gorilla-llm/gorilla-cli and start talking to your CLI!"""
def check_for_updates():
# Check if a new version of gorilla-cli is available once a day
try:
with open(UPDATE_CHECK_FILE, "r") as f:
last_check_date = datetime.datetime.strptime(f.read(), "%Y-%m-%d")
except FileNotFoundError:
last_check_date = datetime.datetime.now() - datetime.timedelta(days=1)
if datetime.datetime.now() - last_check_date >= datetime.timedelta(days=1):
try:
response = requests.get("https://pypi.org/pypi/gorilla-cli/json")
latest_version = response.json()["info"]["version"]
if latest_version > __version__:
print(f"A new version is available: {latest_version}. Update with `pip install --upgrade gorilla-cli`")
except Exception as e:
print("Unable to check for updates:", e)
try:
with open(UPDATE_CHECK_FILE, "w") as f:
f.write(datetime.datetime.now().strftime("%Y-%m-%d"))
except Exception as e:
print("Unable to write update check file:", e)
def get_user_id():
# Unique user identifier for authentication and load balancing
# Gorilla-CLI is hosted by UC Berkeley Sky lab for FREE as a
# research prototype. Please don't spam the system or use it
# for commercial serving. If you would like to request rate
# limit increases for your GitHub handle, please raise an issue.
try:
with open(USERID_FILE, "r") as f:
user_id = str(f.read())
assert user_id != ""
return user_id
except FileNotFoundError:
try:
user_id = (
subprocess.check_output(["git", "config", "--global", "user.email"])
.decode("utf-8")
.strip()
)
print(WELCOME_TEXT)
response = (
input(f"Use your Github handle ({user_id}) as user id? [Y/n]: ")
.strip()
.lower()
)
if response in ["n", "no"]:
user_id = str(uuid.uuid4())
except Exception as e:
issue_title = urllib.parse.quote(
f"Problem with generating userid: {str(e)}"
)
issue_body = urllib.parse.quote(f"Unable to generate userid: {str(e)}")
print("Unable to generate userid:", e)
print(
f"Please run 'go <command>' again. If the problem persists, please raise an issue: \
{ISSUE_URL}?title={issue_title}&body={issue_body}"
)
try:
with open(USERID_FILE, "w") as f:
f.write(user_id)
return user_id
except Exception as e:
issue_title = urllib.parse.quote("Problem with userid file")
issue_body = urllib.parse.quote(f"Unable to write userid file: {str(e)}")
print("Unable to write userid file:", e)
print(
f"Try deleting USERID_FILE and run 'go <command>' again. If the problem persists, please raise an issue:\
{ISSUE_URL}?title={issue_title}&body={issue_body}"
)
def main():
def execute_command(cmd):
process = subprocess.run(cmd, shell=True, stderr=subprocess.PIPE)
error_msg = process.stderr.decode("utf-8")
if error_msg:
print(f"{error_msg}")
return error_msg
return str(process.returncode)
args = sys.argv[1:]
user_input = " ".join(args)
user_id = get_user_id()
# Generate a unique interaction ID
interaction_id = str(uuid.uuid4())
with Halo(text="🦍 Loading", spinner="dots"):
try:
data_json = {
"user_id": user_id,
"user_input": user_input,
"interaction_id": interaction_id,
}
response = requests.post(
f"{SERVER_URL}/commands", json=data_json, timeout=30
)
commands = response.json()
except requests.exceptions.RequestException as e:
print("Server is unreachable.")
print("Try updating Gorilla-CLI with 'pip install --upgrade gorilla-cli'")
return
check_for_updates()
if commands:
selected_command = go_questionary.select(
"", choices=commands, instruction=""
).ask()
exit_condition = execute_command(selected_command)
# Commands failed / succeeded?
try:
response = requests.post(
f"{SERVER_URL}/command-execution-result",
json={
"user_id": user_id,
"command": selected_command,
"exit_condition": exit_condition,
"interaction_id": interaction_id,
},
timeout=30,
)
if response.status_code != 200:
print("Failed to send command execution result to the server.")
except requests.exceptions.Timeout:
print("Failed to send command execution result to the server: Timeout.")
if __name__ == "__main__":
main()