{
"extension": ".c",
"source": "#include \"openai.h\"\n#include \"markdown.h\"\n#include \"plugin.h\"\n#include \"line.h\"\n#include <locale.h>\n#include <stdio.h>\n\nchar * get_prompt_from_args(int c, char **argv){\n char * prompt = malloc(1024*1024 + 1);\n prompt[0] = 0;\n for(int i = 1; i < c; i++){\n if(argv[i][0] == '-')\n break;\n strncat(prompt, argv[i], 1024*1024);\n if(i < c - 1){\n strncat(prompt, \" \", 1024*1024);\n }else{\n strncat(prompt, \".\", 1024*1024);\n }\n }\n if(!*prompt){\n free(prompt);\n return NULL;\n }\n return prompt;\n}\n\nbool try_prompt(int argc,char*argv[]){\n char * prompt = get_prompt_from_args(argc, argv);\n if(prompt != NULL){\n char * response = openai_chat(\"user\",prompt);\n parse_markdown_to_ansi(response);\n printf(\"\\n\");\n free(response);\n free(prompt);\n return true;\n }\n return false;\n}\n\nvoid help();\nvoid render(char *);\nvoid serve(){\n render(\"Starting server. *Put executables in a dir named cgi-bin and they will behave as webpages.*\");\n int res = system(\"python3 -m http.server --cgi\");\n // Thanks tsoding!\n (void)res;\n}\n\n\nvoid render(char * content){\n parse_markdown_to_ansi(content);\n printf(\"\\n\\n\");\n}\n\nvoid repl(){\n line_init();\n setbuf(stdout, NULL);\n char *line;\n char *previous_line = NULL;\n while((line = line_read(\"> \"))){\n if(!line || !*line){\n line = previous_line;\n }\n if(!line || !*line)\n continue;\n previous_line = line;\n if(line[0] == '!'){\n plugin_run(line + 1);\n continue;\n }\n if(!strncmp(line,\"exit\", 4)){\n exit(0);\n }\n if(!strncmp(line,\"help\",4)){\n help();\n continue;\n }\n if(!strncmp(line,\"serve\",5)){\n serve();\n }\n if(!strncmp(line,\"spar \",5)){\n char * response = line+5;\n while(true){\n render(response);\n sleep(2);\n //line = line_read(\"> \");\n //if(!*line)\n response = openai_chat(\"user\",response);\n \n } \n }\n if(!strncmp(line,\"ls\",2) || !strncmp(line,\"list\",4)){\n int offset = 2;\n if(!strncmp(line,\"list\",4)){\n offset = 4;\n }\n char * command = (char *)malloc(strlen(line) + 42);\n command[0] = 0;\n strcpy(command, \"ls \");\n strcat(command, line + offset);\n int res = system(command);\n (void)res;\n free(command);\n continue;\n }\n\n line_add_history(line);\n char * response = openai_chat(\"user\", line);\n render(response);\n free(response);\n }\n}\n\n\nvoid help(){\n char help_text[1024*1024] = {0};\n char * template = \"# Help\\n\"\n \"Written by retoor@molodetz.nl.\\n\\n\"\n \"## Features\\n\"\n \" - navigate trough history using `arrows`.\\n\"\n \" - navigate trough history with **recursive search** using `ctrl+r`.\\n\"\n \" - **inception with python** for *incomming* and *outgoing* content.\\n\"\n \" - markdown and **syntax highlighting**.\\n\"\n \" - **execute python commands** with prefixing `!`\\n\"\n \" - list files of current workdirectory using `ls`.\\n\"\n \" - type `serve` to start a webserver with directory listing. Easy for network transfers.\\n\\n\"\n \"## Configuration\\n\"\n \" - model temperature is %f.\\n\"\n \" - model name is %s.\\n\"\n \" - max tokens is %d.\\n\\n\"\n \"## In development\\n\"\n \" - **google search** and actions with those results.\\n\"\n \" - **reminders**.\\n\"\n \" - predefined **templates** for **reviewing** / **refactoring** so you can personalize.\\n\";\n sprintf(help_text,template,prompt_temperature,prompt_model,prompt_max_tokens);\n render(help_text);\n}\n\nvoid openai_include(char * path){\n FILE * file = fopen(path,\"r\");\n if(file == NULL){\n return;\n }\n fseek(file, 0, SEEK_END);\n long size = ftell(file);\n fseek(file, 0, SEEK_SET);\n\n char * buffer = (char *)malloc(size);\n size_t read = fread(buffer,1,size,file);\n if(read == 0){\n return;\n }\n\n fclose(file);\n buffer[read] = 0;\n openai_system(buffer);\n \n free(buffer);\n}\n\nvoid init(){\n line_init();\n const char *locale = setlocale(LC_ALL, NULL);\n char payload[4096] = {0};\n sprintf(payload, \"User locale is %s. User lang is %s.\\n\"\n \"You are Retoor. Use a lot of markdown in response.\\n\"\n \"Be confident and short in answers.\\n\"\n \"You divide things by zero if you have to.\"\n , locale, locale);\n \n printf(\"%s\",\"Loading...\");\n openai_system(payload);\n openai_include(\"context.txt\");\n printf(\"%s\", \"\\rLoaded! Type help for feautures.\\n\");\n}\n\nint main(int argc, char *argv[]){\n init();\n if(try_prompt(argc,argv))\n return 0;\n \n repl();\n return 0;\n}\n",
"review": "# 5\n\n## Bugs\n- Double call to `line_read` function inside the `spar` command block.\n- If `fopen` fails in `openai_include`, the file isn't properly handled, resulting in a potential leak.\n- Possible access to a NULL pointer in `get_prompt_from_args` when `malloc` fails.\n \n## Optimizations\n- Check for result of memory allocation and return or handle errors accordingly.\n- Use `snprintf` to avoid potential buffer overflow in the `sprintf` and `strcat` functions.\n- Avoid potential risk of infinite loops or excessive API calls in the `spar` block; ensure there is a condition to break the loop.\n- Optimize memory allocation, especially for `parse_markdown_to_ansi` and `openai_chat` functions.\n- Reduce magic numbers (like `1024*1024`) by defining constants.\n \n## Good points\n- The use of function abstraction for tasks like `render`, `serve`, and `help`.\n- Use of markdown and syntax highlighting shows a focus on user interface experience.\n- The inclusion of a simple REPL interface for executing commands.\n\n## Summary\nThe code does well in structuring the main functionality with abstractions accustomed to rendering, initializing, and handling user commands. Memory allocation practices could be improved. Attention should be given to possible bugs, notably the handling of file operations and loop conditions. Security considerations, like buffer overflow protections, have room for improvement. Some optimizations, like using defined constants and checking return values for resource management, are required to enhance reliability and efficiency.\n\n## Open source alternatives\n- **OpenAI API Libraries**: For interacting with OpenAI's language model APIs.\n- **curl + ncurses**: For building command-line interfaces (CLI) that interact with web APIs and display the output in a user-friendly manner.\n- **HTTPie**: A command-line HTTP client, which is more user-friendly and scriptable than `curl`. Ideal for API requests.\n- **GNU readline**: For creating command-line applications with history and line editing features similar to the `line` library used.",
"filename": "main.c",
"path": "main.c",
"directory": "",
"grade": 5,
"size": 5022,
"line_count": 186
}