Skip to content

Commit

Permalink
Added history feature (#54)
Browse files Browse the repository at this point in the history
The history feature (`-p` or `--history`) will allow users to find their
past commands executed and execute them using the questionary selection
feature.

The history will be stored in `~/.gorilla_cli_history` and currently, it
is set so that the newest 5 commands in the history will be displayable
(there is an adjustable constant for `HISTORY_LENGTH`).

Repeated executions of the same command within the most recent 5
commands will not be appended to the history, but as long as that
command is out of the recent window, it is again able to be added to the
history list. This is to prevent cluttering of the history by repeated
executions of the same command consecutively.

This address the issue #39 for bash history appending for executed
commands. Since the CLI, using python, runs on a separate subprocess
than the current user's shell, it is against best security practices to
violate this subprocess distinction and force write to a global history.
As well, since different shells work differently when tracking history
(zsh, bash, cmd.exe), it is also a very big hassle to introduce
cross-platform support. This is why I opted for this in-house history
solution.

<img width="692" alt="image"
src="https://github.com/gorilla-llm/gorilla-cli/assets/65890703/a1edd64f-a0da-4df6-a9c1-0b177bb4d0bb">
  • Loading branch information
royh02 authored Oct 19, 2023
1 parent 386153a commit d99a81a
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 17 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,24 @@ $ gorilla get the image ids of all pods running in all namespaces in kubernetes

Gorilla-CLI fuses the capabilities of various Language Learning Models (LLMs) like [Gorilla LLM](https://github.com/ShishirPatil/gorilla/), OpenAI's GPT-4, Claude v1, and others to present a user-friendly command-line interface. For each user query, we gather responses from all contributing LLMs, filter, sort, and present you with the most relevant options.

### Arguments

```
usage: go_cli.py [-h] [-p] [command_args ...]
Gorilla CLI Help Doc
positional arguments:
command_args Prompt to be inputted to Gorilla
optional arguments:
-h, --help show this help message and exit
-p, --history Display command history
```

The history feature lets the user go back to previous commands they've executed to re-execute in a similar fashion to terminal history.


## Contributions

We welcome your enhancements to Gorilla CLI! If you have improvements, feel free to submit a pull request on our GitHub page.
Expand Down
98 changes: 81 additions & 17 deletions go_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import platform
import requests
import subprocess
import argparse
import termios
import urllib.parse
import sys
Expand All @@ -30,8 +31,10 @@
SERVER_URL = "https://cli.gorilla-llm.com"
UPDATE_CHECK_FILE = os.path.expanduser("~/.gorilla-cli-last-update-check")
USERID_FILE = os.path.expanduser("~/.gorilla-cli-userid")
HISTORY_FILE = os.path.expanduser("~/.gorilla_cli_history")
ISSUE_URL = f"https://github.com/gorilla-llm/gorilla-cli/issues/new"
GORILLA_EMOJI = "🦍 " if go_questionary.try_encode_gorilla() else ""
HISTORY_LENGTH = 10
WELCOME_TEXT = f"""===***===
{GORILLA_EMOJI}Welcome to Gorilla-CLI! Enhance your Command Line with the power of LLMs!
Expand Down Expand Up @@ -142,6 +145,8 @@ def get_user_id():
except Exception as e:
print(f"Git not installed. Unable to import userid from Git.")
print(f"Will use a random user-id.")
print("Try running:\n")
print("git config --global user.email <your_email>\n\n")
user_id = generate_random_uid()
print(WELCOME_TEXT)

Expand All @@ -154,46 +159,105 @@ def get_user_id():
print(f"Using a temporary UID {user_id} for now.")
return user_id

def format_command(input_str):
"""
Standardize commands to be stored with a newline
character in the history
"""
if not input_str.endswith('\n'):
input_str += '\n'
return input_str

def append_string_to_file_if_missing(file_path, target_string):
"""
Don't append command to history file if it already exists.
"""
try:
with open(file_path, 'r') as file:
lines = file.readlines()

# Check if the target string is already in the file
if target_string not in lines[-HISTORY_LENGTH:]:
with open(file_path, 'a') as file:
file.write(target_string)
except FileNotFoundError:
# If the file doesn't exist, create it and append the string
with open(file_path, 'w') as file:
file.write(target_string)


def main():
def execute_command(cmd):
cmd = format_command(cmd)
process = subprocess.run(cmd, shell=True, stderr=subprocess.PIPE)

save = not cmd.startswith(':')
if save:
append_string_to_file_if_missing(HISTORY_FILE, cmd)

error_msg = process.stderr.decode("utf-8", "ignore")
if error_msg:
print(f"{error_msg}")
return error_msg
return str(process.returncode)

def get_history_commands(history_file):
"""
Takes in history file
Returns None if file doesn't exist or empty
Returns list of last 10 history commands in the file if it exists
"""
if os.path.isfile(history_file):
with open(history_file, 'r') as history:
lines = history.readlines()
if not lines:
print("No command history.")
return lines[-HISTORY_LENGTH:]
else:
print("No command history.")
return

args = sys.argv[1:]
user_input = " ".join(args)
user_id = get_user_id()
system_info = get_system_info()


# Parse command-line arguments
parser = argparse.ArgumentParser(description="Gorilla CLI Help Doc")
parser.add_argument("-p", "--history", action="store_true", help="Display command history")
parser.add_argument("command_args", nargs='*', help="Prompt to be inputted to Gorilla")

args = parser.parse_args()

# Generate a unique interaction ID
interaction_id = str(uuid.uuid4())

with Halo(text=f"{GORILLA_EMOJI}Loading", spinner="dots"):
try:
data_json = {
"user_id": user_id,
"user_input": user_input,
"interaction_id": interaction_id,
"system_info": system_info,
}
response = requests.post(
f"{SERVER_URL}/commands_v2", 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
if args.history:
commands = get_history_commands(HISTORY_FILE)
else:
with Halo(text=f"{GORILLA_EMOJI}Loading", spinner="dots"):
try:
data_json = {
"user_id": user_id,
"user_input": user_input,
"interaction_id": interaction_id,
"system_info": system_info
}
response = requests.post(
f"{SERVER_URL}/commands_v2", 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=""
"", choices=commands, instruction="Welcome to Gorilla. Use arrow keys to select. Ctrl-C to Exit"
).ask()

if not selected_command:
Expand Down

0 comments on commit d99a81a

Please sign in to comment.