diff --git a/installer/client/cli/fabric.py b/installer/client/cli/fabric.py index e075573..69c6350 100755 --- a/installer/client/cli/fabric.py +++ b/installer/client/cli/fabric.py @@ -1,4 +1,4 @@ -from .utils import Standalone, Update, Setup, Alias +from .utils import Standalone, Update, Setup, Alias, eprint import argparse import sys import os @@ -72,7 +72,7 @@ def main(): Alias() sys.exit() if not os.path.exists(env_file) or not os.path.exists(config_patterns_directory): - print("Please run --setup to set up your API key and download patterns.") + eprint("Please run --setup to set up your API key and download patterns.") sys.exit() if not os.path.exists(config_patterns_directory): Update() @@ -80,7 +80,7 @@ def main(): sys.exit() if args.changeDefaultModel: Setup().default_model(args.changeDefaultModel) - print(f"Default model changed to {args.changeDefaultModel}") + eprint(f"Default model changed to {args.changeDefaultModel}") sys.exit() if args.agents: # Handle the agents logic @@ -99,11 +99,11 @@ def main(): sys.exit() if args.context: if not os.path.exists(os.path.join(config, "context.md")): - print("Please create a context.md file in ~/.config/fabric") + eprint("Please create a context.md file in ~/.config/fabric") sys.exit() if args.clear: Setup().clean_env() - print("Model choice cleared. please restart your session to use the --model flag.") + eprint("Model choice cleared. please restart your session to use the --model flag.") sys.exit() standalone = Standalone(args, args.pattern) if args.list: @@ -113,19 +113,19 @@ def main(): print(d) sys.exit() except FileNotFoundError: - print("No patterns found") + eprint("No patterns found") sys.exit() if args.listmodels: gptmodels, localmodels, claudemodels = standalone.fetch_available_models() - print("GPT Models:") + eprint("GPT Models:") for model in gptmodels: - print(model) - print("\nLocal Models:") + eprint(model) + eprint("\nLocal Models:") for model in localmodels: - print(model) - print("\nClaude Models:") + eprint(model) + eprint("\nClaude Models:") for model in claudemodels: - print(model) + eprint(model) sys.exit() if args.text is not None: text = args.text diff --git a/installer/client/cli/utils.py b/installer/client/cli/utils.py index defcd59..450be0d 100644 --- a/installer/client/cli/utils.py +++ b/installer/client/cli/utils.py @@ -16,6 +16,9 @@ config_directory = os.path.expanduser("~/.config/fabric") env_file = os.path.join(config_directory, ".env") +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + class Standalone: def __init__(self, args, pattern="", env_file="~/.config/fabric/.env"): """ Initialize the class with the provided arguments and environment file. @@ -41,7 +44,7 @@ class Standalone: self.client = OpenAI() self.client.api_key = apikey except: - print("No API key found. Use the --apikey option to set the key") + eprint("No API key found. Use the --apikey option to set the key") self.local = False self.config_pattern_directory = config_directory self.pattern = pattern @@ -129,7 +132,7 @@ class Standalone: system_message = {"role": "system", "content": system} messages = [system_message, user_message] except FileNotFoundError: - print("pattern not found") + eprint("pattern not found") return else: if context: @@ -169,17 +172,17 @@ class Standalone: sys.stdout.flush() except Exception as e: if "All connection attempts failed" in str(e): - print( + eprint( "Error: cannot connect to llama2. If you have not already, please visit https://ollama.com for installation instructions") if "CLAUDE_API_KEY" in str(e): - print( + eprint( "Error: CLAUDE_API_KEY not found in environment variables. Please run --setup and add the key") if "overloaded_error" in str(e): - print( + eprint( "Error: Fabric is working fine, but claude is overloaded. Please try again later.") else: - print(f"Error: {e}") - print(e) + eprint(f"Error: {e}") + eprint(e) if self.args.copy: pyperclip.copy(buffer) if self.args.output: @@ -215,7 +218,7 @@ class Standalone: system_message = {"role": "system", "content": system} messages = [system_message, user_message] except FileNotFoundError: - print("pattern not found") + eprint("pattern not found") return else: if context: @@ -243,19 +246,19 @@ class Standalone: print(response.choices[0].message.content) except Exception as e: if "All connection attempts failed" in str(e): - print( + eprint( "Error: cannot connect to llama2. If you have not already, please visit https://ollama.com for installation instructions") if "CLAUDE_API_KEY" in str(e): - print( + eprint( "Error: CLAUDE_API_KEY not found in environment variables. Please run --setup and add the key") if "overloaded_error" in str(e): - print( + eprint( "Error: Fabric is working fine, but claude is overloaded. Please try again later.") if "Attempted to call a sync iterator on an async stream" in str(e): - print("Error: There is a problem connecting fabric with your local ollama installation. Please visit https://ollama.com for installation instructions. It is possible that you have chosen the wrong model. Please run fabric --listmodels to see the available models and choose the right one with fabric --model or fabric --changeDefaultModel. If this does not work. Restart your computer (always a good idea) and try again. If you are still having problems, please visit https://ollama.com for installation instructions.") + eprint("Error: There is a problem connecting fabric with your local ollama installation. Please visit https://ollama.com for installation instructions. It is possible that you have chosen the wrong model. Please run fabric --listmodels to see the available models and choose the right one with fabric --model or fabric --changeDefaultModel. If this does not work. Restart your computer (always a good idea) and try again. If you are still having problems, please visit https://ollama.com for installation instructions.") else: - print(f"Error: {e}") - print(e) + eprint(f"Error: {e}") + eprint(e) if self.args.copy: pyperclip.copy(response.choices[0].message.content) if self.args.output: @@ -285,10 +288,10 @@ class Standalone: for model in sorted_gpt_models: gptlist.append(model.get("id")) else: - print(f"Failed to fetch models: HTTP {response.status_code}") + eprint(f"Failed to fetch models: HTTP {response.status_code}") sys.exit() except: - print('No OpenAI API key found. Please run fabric --setup and add the key if you wish to interact with openai') + eprint('No OpenAI API key found. Please run fabric --setup and add the key if you wish to interact with openai') import ollama try: default_modelollamaList = ollama.list()['models'] @@ -327,7 +330,7 @@ class Update: self.pattern_directory = os.path.join( self.config_directory, "patterns") os.makedirs(self.pattern_directory, exist_ok=True) - print("Updating patterns...") + eprint("Updating patterns...") self.update_patterns() # Start the update process immediately def update_patterns(self): @@ -344,9 +347,9 @@ class Update: if os.path.exists(self.pattern_directory): shutil.rmtree(self.pattern_directory) shutil.copytree(patterns_source_path, self.pattern_directory) - print("Patterns updated successfully.") + eprint("Patterns updated successfully.") else: - print("Patterns folder not found in the downloaded zip.") + eprint("Patterns folder not found in the downloaded zip.") def download_zip(self, url, save_path): """Download the zip file from the specified URL.""" @@ -354,13 +357,13 @@ class Update: response.raise_for_status() # Check if the download was successful with open(save_path, 'wb') as f: f.write(response.content) - print("Downloaded zip file successfully.") + eprint("Downloaded zip file successfully.") def extract_zip(self, zip_path, extract_to): """Extract the zip file to the specified directory.""" with zipfile.ZipFile(zip_path, 'r') as zip_ref: zip_ref.extractall(extract_to) - print("Extracted zip file successfully.") + eprint("Extracted zip file successfully.") return extract_to # Return the path to the extracted contents @@ -374,7 +377,7 @@ class Alias: home_directory, ".config/fabric/fabric-bootstrap.inc")) self.remove_all_patterns() self.add_patterns() - print('Aliases added successfully. Please restart your terminal to use them.') + eprint('Aliases added successfully. Please restart your terminal to use them.') def add(self, name, alias): for file in self.config_files: @@ -455,7 +458,7 @@ class Setup: for model in sorted_gpt_models: self.gptlist.append(model.get("id")) else: - print(f"Failed to fetch models: HTTP {response.status_code}") + eprint(f"Failed to fetch models: HTTP {response.status_code}") sys.exit() import ollama try: @@ -483,7 +486,7 @@ class Setup: if not os.path.exists(self.env_file) and api_key: with open(self.env_file, "w") as f: f.write(f"OPENAI_API_KEY={api_key}\n") - print(f"OpenAI API key set to {api_key}") + eprint(f"OpenAI API key set to {api_key}") elif api_key: # erase the line OPENAI_API_KEY=key and write the new key with open(self.env_file, "r") as f: @@ -615,7 +618,7 @@ class Setup: sh_config = os.path.join( user_home, ".config/fabric/fabric-bootstrap.inc") else: - print("No environment file found.") + eprint("No environment file found.") if sh_config: with open(sh_config, "r") as f: lines = f.readlines() @@ -632,7 +635,7 @@ class Setup: f.write(modified_line) self.remove_duplicates(env_file) else: - print("No shell configuration file found.") + eprint("No shell configuration file found.") def default_model(self, model): """Set the default model in the environment file. @@ -645,7 +648,7 @@ class Setup: # Write or update the DEFAULT_MODEL in env_file allModels = self.claudeList + self.fullOllamaList + self.gptlist if model not in allModels: - print( + eprint( f"Error: {model} is not a valid model. Please run fabric --listmodels to see the available models.") sys.exit() @@ -672,10 +675,10 @@ class Setup: modified_line = self.update_fabric_alias( modified_line, model) f.write(modified_line) - print(f"""Default model changed to { + eprint(f"""Default model changed to { model}. Please restart your terminal to use it.""") else: - print("No shell configuration file found.") + eprint("No shell configuration file found.") def remove_duplicates(self, filename): unique_lines = set() @@ -706,14 +709,14 @@ class Setup: None """ - print("Welcome to Fabric. Let's get started.") + eprint("Welcome to Fabric. Let's get started.") apikey = input( "Please enter your OpenAI API key. If you do not have one or if you have already entered it, press enter.\n") self.api_key(apikey) - print("Please enter your claude API key. If you do not have one, or if you have already entered it, press enter.\n") + eprint("Please enter your claude API key. If you do not have one, or if you have already entered it, press enter.\n") claudekey = input() self.claude_key(claudekey) - print("Please enter your YouTube API key. If you do not have one, or if you have already entered it, press enter.\n") + eprint("Please enter your YouTube API key. If you do not have one, or if you have already entered it, press enter.\n") youtubekey = input() self.youtube_key(youtubekey) self.patterns() @@ -745,7 +748,7 @@ class Transcribe: transcript += segment['text'] + " " return transcript.strip() except Exception as e: - print("Error:", e) + eprint("Error:", e) return None @@ -757,7 +760,7 @@ class AgentSetup: None """ - print("Welcome to Fabric. Let's get started.") + eprint("Welcome to Fabric. Let's get started.") browserless = input("Please enter your Browserless API key\n").strip() serper = input("Please enter your Serper API key\n").strip()