diff --git a/Makefile b/Makefile index f0adc7e..5a5ca2c 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ all: build run build: - gcc main.c -lcurl -lssl -lcrypto -ljson-c -Ofast -o r -Werror -Wall -lpython3.14 -I/usr/include/python3.14 -lreadline -lncurses + # -lpython3.14 -I/usr/include/python3.14 + gcc main.c -lcurl -lssl -lcrypto -ljson-c -Ofast -o r -Werror -Wall -lreadline -lncurses publish r build_free: - gcc main.c -lcurl -DFREE_VERSION -lssl -lcrypto -ljson-c -Ofast -o rf -Werror -Wall -lpython3.14 -I/usr/include/python3.14 -lreadline -lncurses + gcc main.c -lcurl -DFREE_VERSION -lssl -lcrypto -ljson-c -Ofast -o rf -Werror -Wall -lreadline -lncurses publish rf run: diff --git a/main.c b/main.c index 4a119b6..d5d9b02 100644 --- a/main.c +++ b/main.c @@ -30,7 +30,6 @@ #include "openai.h" #include "markdown.h" -#include "plugin.h" #include "line.h" #include <locale.h> #include <stdio.h> @@ -38,6 +37,13 @@ #include <string.h> #include <unistd.h> +bool SYNTAX_HIGHLIGHT_ENABLED = true; +bool API_MODE = false; +void help(); +void render(char *); +bool openai_include(char *path); +char * strreplace(char * content, char * what, char * with); + char * get_prompt_from_stdin(char * prompt) { int index = 0; prompt[index] = '\0'; @@ -50,21 +56,49 @@ char * get_prompt_from_stdin(char * prompt) { } char *get_prompt_from_args(int c, char **argv) { - char *prompt = malloc(1024 * 1024 * 10 + 1); + char *prompt = (char *)malloc(1024 * 1024 * 10 + 1); + char *system = (char *)malloc(1024*1024); + + system[0] = 0; prompt[0] = 0; + bool get_from_std_in = false; for (int i = 1; i < c; i++) { if (!strcmp(argv[i],"--stdin")){ - prompt = get_prompt_from_stdin(prompt); - break; - }else{ - strcat(prompt, argv[i]); + fprintf(stderr, "%s\n", "Reading from stdin."); + get_from_std_in = true; + }else if(!strcmp(argv[i],"--context")){ + if(i+1 <= c){ + char * context_file_path = argv[i+1]; + fprintf(stderr, "Including \"%s\".\n", context_file_path); + openai_include(context_file_path); + i++; + } + }else if(!strcmp(argv[i],"--api")){ + API_MODE = true; + }else if(!strcmp(argv[i], "--nh")){ + SYNTAX_HIGHLIGHT_ENABLED = false; + fprintf(stderr, "%s\n", "Syntax highlighting disabled."); + }else if (!get_from_std_in){ + strcat(system, argv[i]); if (i < c - 1) { - strcat(prompt, " "); + strcat(system, " "); } else { - strcat(prompt, ". "); + strcat(system, "."); } } } + + if(get_from_std_in){ + if(*system){ + openai_system(system); + } + free(system); + prompt = get_prompt_from_stdin(prompt); + }else{ + free(prompt); + prompt = system; + } + if (!*prompt) { free(prompt); return NULL; @@ -81,8 +115,7 @@ bool try_prompt(int argc, char *argv[]) { free(prompt); return false; } - parse_markdown_to_ansi(response); - printf("\n"); + render(response); free(response); free(prompt); return true; @@ -90,17 +123,132 @@ bool try_prompt(int argc, char *argv[]) { return false; } -void help(); -void render(char *); void serve() { render("Starting server. *Put executables in a dir named cgi-bin and they will behave as web pages.*"); int res = system("python3 -m http.server --cgi"); (void)res; } -void render(char *content) { - parse_markdown_to_ansi(content); - printf("\n\n"); +char ** get_parameters(char * content, char * delimiter){ + char * start = NULL; + char ** parameters = NULL; //(char **)malloc(sizeof(char *) * 2); + int count = 0; + while((start = strstr(content, delimiter)) != NULL){ + start += 3; + char * end = strstr(start, delimiter); + char * parameter = (char *)malloc(end - start + 1); + + memcpy(parameter, start, end - start); + parameter[end - start] = '\0'; + + // printf("%s\n", parameter); + content = end + 3; + count+=1; + parameters = (char **)realloc(parameters, sizeof(char *) * (1+count*2)); + parameters[count-1] = parameter; + parameters[count] = NULL; + + } + + return parameters; +} + +void render(char *content){ + + char ** parameters = get_parameters(content,"\"\"\""); + int parameter_index = 0; + bool print_result = true; + while(parameters){ + char * parameter = parameters[parameter_index]; + if(!parameter) + break; + print_result = false; + if(!strcmp(parameter, "!find_note")){ + char * note_name = parameters[parameter_index + 1]; + FILE * file = fopen("notes.txt", "r"); + fseek(file, 0, SEEK_END); + long size = ftell(file); + fseek(file, 0, SEEK_SET); + + char *buffer = (char *)malloc(size + 1); + size = fread(buffer, 1, size, file); + buffer[size] = '\0'; + fclose(file); + char * prompt = (char *)malloc(size + 1000); + prompt[0] = 0; + sprintf(prompt,"This are records seperated by newline: ```%s```. Respond to use with record that is about ```%s```. Rspond in plain text, do not execute command.",buffer, note_name); + char* result = openai_chat("user",prompt); + printf("%s\n",result); + free(prompt); + free(result); + free(buffer); + } + + if(!strcmp(parameter, "!write_note")){ + char * file_name = "notes.txt"; + char * file_content = parameters[parameter_index + 1]; + FILE * file = fopen(file_name, "a+"); + fprintf(file, "%s\n\n", file_content); + fclose(file); + } + if(!strcmp(parameter, "!write_file")){ + + char * file_name = parameters[parameter_index + 1]; + + printf("Writing to file: %s\n",file_name); + char * file_content = parameters[parameter_index + 2]; + FILE * file = fopen(file_name, "w"); + fprintf(file, "%s", file_content); + fclose(file); + + } + if(!strcmp(parameter, "!system")){ + // printf("%s\n",parameters[parameter_index+1]); + char * command = parameters[parameter_index + 1]; + FILE * f = popen(command,"r");; + if(!f){ + printf("Execution failed: %s\n",command); + } + char buffer[4096]; + char * full_buffer = (char *)malloc(1); + int bytes_read = 0; + while (fgets(buffer, sizeof(buffer), f) != NULL) { + full_buffer = realloc(full_buffer, bytes_read + strlen(buffer) + 1); + memcpy(full_buffer + bytes_read, buffer, strlen(buffer)); + bytes_read += strlen(buffer); + printf("%s",buffer); + fflush(stdout); + } + pclose(f); + full_buffer[bytes_read] = '\0'; + //printf("%s",full_buffer); + char * prompt = (char *)malloc(strlen(full_buffer) + 1000); + prompt[0] = 0; + printf(prompt,"Last execution result and thus current context is: ```%s```\n",full_buffer); + char * rmsg = openai_chat("system",full_buffer); + + //printf("%s\n",rmsg); + free(prompt); + free(rmsg); + free(full_buffer); + + }else if(parameter[0] == '!'){ + printf("%s\n",parameter); + } + parameter_index+= 1; + + } + if(!print_result){ + return; + } + + if(SYNTAX_HIGHLIGHT_ENABLED) + { + parse_markdown_to_ansi(content); + printf("\n\n"); + }else{ + printf("%s", content); + } } void repl() { @@ -114,10 +262,7 @@ void repl() { if (!line || !*line) continue; previous_line = line; - if (line[0] == '!') { - plugin_run(line + 1); - continue; - } + if (!strncmp(line, "exit", 4)) { exit(0); } @@ -126,8 +271,12 @@ void repl() { continue; } if (!strncmp(line, "serve", 5)) { + continue ; serve(); } + if(!strncmp(line,"retoor",6)){ + openai_include("retoor"); + } if (!strncmp(line, "spar ", 5)) { char *response = line + 5; while (true) { @@ -136,7 +285,8 @@ void repl() { response = openai_chat("user", response); } } - if (!strncmp(line, "ls", 2) || !strncmp(line, "list", 4)) { + if (!strncmp(line, "/_", 2) || !strncmp(line, "____", 4)) { + continue; int offset = 2; if (!strncmp(line, "list", 4)) { offset = 4; @@ -154,6 +304,7 @@ void repl() { line_add_history(line); char *response = openai_chat("user", line); render(response); + printf("\n"); free(response); } } @@ -183,7 +334,49 @@ void help() { render(help_text); } +char * strreplace(char * content, char * what, char * with){ + char * pos = strstr(content, what); + if(!pos){ + return strdup(content); + } + char * result = (char *)malloc(strlen(content) + strlen(with) + 5); + memset(result, 0, strlen(content) + strlen(with) + 3); + memcpy(result, content, pos - content); + memcpy(result + (pos - content), with, strlen(with)); + memcpy(result + (pos - content) + strlen(with), pos + strlen(what), strlen(content) - (pos - content) - strlen(what) + 1); + return result; +} + +char * linux_instructions = + "You are a linux master and are able to transform the prompt of " + "user into shell commands that will be executed on a debian " + "based system. You can execute shell commands by responding with python code: " + "literally `\"\"\"!system\"\"\",\"\"\"`your shell command`\"\"\". Execute immediately. Read bash history file if you have to work with history."; +char * retoor_instructions = "If the user prompts with social talk, " + "respond like replica and emoji. Your name is retoor and made by molodetz. Be interested. Be creative."; + bool openai_include(char *path) { + if(!strcmp(path,"retoor")){ + render("**Loading retoor.**"); + size_t new_size = strlen(linux_instructions) + strlen(retoor_instructions)+10; + char * all = (char *)malloc(new_size); + memset(all,0,new_size); + strcpy(all,linux_instructions); + strcat(all,retoor_instructions); + openai_chat("system",all); + free(all); + render("**Retoor is loaded. Retoor can do bash. Retoor can do all the bash.**"); + render("Let's diagnose your computer and network together by asking things like: \n" + " 1. how many devices are there on my network? Check also MDNS devices. \n" + " 2 does my network does something suspicious? \n" + " 3. can you benchmark https://molodetz.nl?\n" + " 4. do i run strange processes?\n" + " 5. what is the performance of my pc?\n" + " 6. describe my hardware.\n" + " 7. please make a backup from my current directory.\n" + " 8. find ten largest folders on my pc using sudo."); + return true; + } FILE *file = fopen(path, "r"); if (file == NULL) { return false; @@ -200,8 +393,11 @@ bool openai_include(char *path) { fclose(file); buffer[read] = '\0'; - openai_system(buffer); - + char * replaced_linux = strreplace(buffer,"[linux]", linux_instructions); + char * replaced_retoor = strreplace(replaced_linux,"[retoor]", retoor_instructions); + openai_system(replaced_retoor); + free(replaced_retoor); + free(replaced_linux); free(buffer); return true; } @@ -212,15 +408,15 @@ void init() { const char *locale = setlocale(LC_ALL, NULL); char payload[4096] = {0}; sprintf(payload, "Your locale is %s. User lang is %s.", locale, locale); - printf("%s", "Loading... ⏳"); + fprintf(stderr, "%s", "Loading... ⏳"); openai_system(payload); if(!openai_include(".rcontext.txt")){ openai_include("~/.rcontext.txt"); } #ifndef FREE_VERSION - printf("%s", "\r✅ Commercial version. Type help for features.\n"); + fprintf(stderr, "%s", "\r✅ Commercial version. Type help for features.\n"); #else - printf("%s","\r✅ Free version (GPT-3.5 Turbo), for you by retoor.\n"); + fprintf(stderr, "%s","\r✅ Free version (GPT-3.5 Turbo), for you by retoor.\n"); #endif }