""" idxtool is a script is used to perform various GPT indexing and searching tasks - Reformat all the GPT files in the source path and save them to the destination path. - Rename all the GPTs to include their ChatGPT/g/ID in the filename. - Generate TOC - etc. """ import sys, os, argparse from gptparser import GptMarkdownFile, enum_gpts, parse_gpturl from typing import Tuple from urllib.parse import quote TOC_FILENAME = 'TOC.md' TOC_GPT_MARKER_LINE = '- GPTs' def get_toc_file() -> str: return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', TOC_FILENAME)) def update_logo(filename): if filename == '*': print("TODO: Updating logo for all GPT files") else: print(f"TODO: Updating logo with file: {filename}") raise NotImplementedError def update_description(filename): if filename == '*': print("TODO: Updating description for all GPT files") else: print(f"TODO Updating description with file: {filename}") raise NotImplementedError def rename_gpts(): nb_ok = nb_total = 0 all_renamed_already = True for ok, gpt in enum_gpts(): nb_total += 1 if not ok or not (id := gpt.id()): print(f"[!] {gpt.filename}") continue # Skip files with correct prefix basename = os.path.basename(gpt.filename) if basename.startswith(f"{id.id}_"): nb_ok += 1 continue all_renamed_already = False # New full file name with ID prefix new_fn = os.path.join(os.path.dirname(gpt.filename), f"{id.id}_{basename}") print(f"[+] {basename} -> {os.path.basename(new_fn)}") if os.system(f"git mv \"{gpt.filename}\" \"{new_fn}\"") == 0: nb_ok += 1 msg = f"Renamed {nb_ok} out of {nb_total} GPT files." ok = nb_ok == nb_total if all_renamed_already: msg = f"All {nb_total} GPT files were already renamed. No action taken." print(msg) return (ok, msg) def parse_gpt_file(filename) -> Tuple[bool, str]: ok, gpt = GptMarkdownFile.parse(filename) if ok: file_name_without_ext = os.path.splitext(os.path.basename(filename))[0] dst_fn = os.path.join( os.path.dirname(filename), f"{file_name_without_ext}.new.md") gpt.save(dst_fn) else: print(gpt) return (ok, gpt) def rebuild_toc(toc_out: str = '') -> Tuple[bool, str]: """ Rebuilds the table of contents (TOC.md) file by reading all the GPT files in the prompts/gpts directory. """ if not toc_out: print(f"Rebuilding Table of Contents (TOC.md) in place") else: print(f"Rebuilding Table of Contents (TOC.md) to '{toc_out}'") toc_in = get_toc_file() if not toc_out: toc_out = toc_in if not os.path.exists(toc_in): return (False, f"TOC File '{toc_in}' does not exist.") # Read the TOC file and find the marker line for the GPT instructions out = [] marker_found = False with open(toc_in, 'r', encoding='utf-8') as file: for line in file: if line.startswith(TOC_GPT_MARKER_LINE): marker_found = True break else: out.append(line) if not marker_found: return (False, f"Could not find the marker '{TOC_GPT_MARKER_LINE}' in '{toc_in}'.") # Write the TOC file all the way up to the marker line try: ofile = open(toc_out, 'w', encoding='utf-8') except: return (False, f"Failed to open '{toc_out}' for writing.") # Write the marker line and each GPT entry out.append(f"{TOC_GPT_MARKER_LINE}\n") nb_ok = nb_total = 0 for ok, gpt in enum_gpts(): nb_total += 1 if ok and (id := gpt.id()): nb_ok += 1 file_link = f"./prompts/gpts/{quote(os.path.basename(gpt.filename))}" version = f" {gpt.get('version')}" if gpt.get('version') else '' out.append(f" - [{gpt.get('title')}{version} (id: {id.id})]({file_link})\n") else: print(f"[!] {gpt.filename}") ofile.writelines(out) ofile.close() msg = f"Generated TOC with {nb_ok} out of {nb_total} GPTs." ok = nb_ok == nb_total if ok: print(msg) return (ok, msg) def find_gpt_in_toc(gptid_or_string): print(f"TODO: Searching TOC.md for GPT ID or string: {gptid_or_string}") raise NotImplementedError def find_gptfile(keyword): keyword = keyword.strip().tolower() # Response file with a set of GPT IDs if keyword.startswith('@'): print(f"TODO: Finding GPT file with ID: {keyword}") if gpt_info := parse_gpturl(keyword): keyword = gpt_info.id print(f"TODO: Finding GPT with ID: {keyword}") raise NotImplementedError def main(): parser = argparse.ArgumentParser(description='idxtool: A GPT indexing and searching tool for the CSP repo') parser.add_argument('--update-logo', type=str, help='Update the logos of the GPT file') parser.add_argument('--toc', nargs='?', const='', type=str, help='Rebuild the table of contents (TOC.md) file') parser.add_argument('--update-description', type=str, help='Update the descriptions of the GPT file') parser.add_argument('--find-gptfile', type=str, help='Find a GPT by its ID or name') parser.add_argument('--find-gpttoc', type=str, help='Searches the TOC.md file for the given gptid or free style string') parser.add_argument('--parse-gptfile', type=str, help='Parses a GPT file name') parser.add_argument('--rename', action='store_true', help='Rename the GPT file names to include their GPT ID') # Handle arguments ok = True args = parser.parse_args() if args.update_logo: update_logo(args.update_logo) if args.parse_gptfile: ok, err = parse_gpt_file(args.parse_gptfile) if not ok: print(err) if args.toc is not None: ok, err = rebuild_toc(args.toc) if not ok: print(err) if args.update_description: update_description(args.update_description) if args.find_gptfile: find_gptfile(args.find_gptfile) if args.find_gpttoc: find_gpt_in_toc(args.find_gpttoc) if args.rename: ok, err = rename_gpts() if not ok: print(err) sys.exit(0 if ok else 1) if __name__ == "__main__": main()