Compare commits
	
		
			No commits in common. "d740eb62a145b18f85f29968531b5af8bd827c42" and "f5994bc03b2c3b41c471463bc2beaa7464b140cc" have entirely different histories.
		
	
	
		
			d740eb62a1
			...
			f5994bc03b
		
	
		
							
								
								
									
										0
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								Dockerfile
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								Dockerfile
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										4
									
								
								chat.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								chat.h
									
									
									
									
									
								
							| @ -51,8 +51,8 @@ char *chat_json(const char *role, const char *message) { | |||||||
| 
 | 
 | ||||||
|   if (role != NULL && message != NULL) { |   if (role != NULL && message != NULL) { | ||||||
|     message_add(role, message); |     message_add(role, message); | ||||||
|     if (use_tools()) { |     if(use_tools()){ | ||||||
|       json_object_object_add(root_object, "tools", tools_descriptions()); |         json_object_object_add(root_object, "tools", tools_descriptions()); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								compose.yml
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								compose.yml
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								database.db
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								database.db
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								db_utils.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								db_utils.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								db_utils.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								db_utils.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										10
									
								
								http_curl.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								http_curl.h
									
									
									
									
									
								
							| @ -68,8 +68,7 @@ char *curl_post(const char *url, const char *data) { | |||||||
|     curl_easy_setopt(curl, CURLOPT_URL, url); |     curl_easy_setopt(curl, CURLOPT_URL, url); | ||||||
|     headers = curl_slist_append(headers, "Content-Type: application/json"); |     headers = curl_slist_append(headers, "Content-Type: application/json"); | ||||||
|     char bearer_header[1337]; |     char bearer_header[1337]; | ||||||
|     snprintf(bearer_header, sizeof(bearer_header), "Authorization: Bearer %s", |     sprintf(bearer_header, "Authorization: Bearer %s", resolve_api_key()); | ||||||
|              resolve_api_key()); |  | ||||||
|     headers = curl_slist_append(headers, bearer_header); |     headers = curl_slist_append(headers, bearer_header); | ||||||
|     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); |     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); | ||||||
|     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); |     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); | ||||||
| @ -85,7 +84,6 @@ char *curl_post(const char *url, const char *data) { | |||||||
|     curl_easy_cleanup(curl); |     curl_easy_cleanup(curl); | ||||||
|     return response.data; |     return response.data; | ||||||
|   } |   } | ||||||
|   free(response.data); |  | ||||||
|   return NULL; |   return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -103,8 +101,7 @@ char *curl_get(const char *url) { | |||||||
|     curl_easy_setopt(curl, CURLOPT_URL, url); |     curl_easy_setopt(curl, CURLOPT_URL, url); | ||||||
|     headers = curl_slist_append(headers, "Content-Type: application/json"); |     headers = curl_slist_append(headers, "Content-Type: application/json"); | ||||||
|     char bearer_header[1337]; |     char bearer_header[1337]; | ||||||
|     snprintf(bearer_header, sizeof(bearer_header), "Authorization: Bearer %s", |     sprintf(bearer_header, "Authorization: Bearer %s", resolve_api_key()); | ||||||
|              resolve_api_key()); |  | ||||||
|     headers = curl_slist_append(headers, bearer_header); |     headers = curl_slist_append(headers, bearer_header); | ||||||
|     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); |     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); | ||||||
|     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); |     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); | ||||||
| @ -115,9 +112,6 @@ char *curl_get(const char *url) { | |||||||
|     } |     } | ||||||
|     curl_slist_free_all(headers); |     curl_slist_free_all(headers); | ||||||
|     curl_easy_cleanup(curl); |     curl_easy_cleanup(curl); | ||||||
|   } else { |  | ||||||
|     free(response.data); |  | ||||||
|     return NULL; |  | ||||||
|   } |   } | ||||||
|   return response.data; |   return response.data; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										426
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										426
									
								
								main.c
									
									
									
									
									
								
							| @ -1,8 +1,8 @@ | |||||||
|  | #include "r.h" | ||||||
| #include "db_utils.h" | #include "db_utils.h" | ||||||
| #include "line.h" | #include "line.h" | ||||||
| #include "markdown.h" | #include "markdown.h" | ||||||
| #include "openai.h" | #include "openai.h" | ||||||
| #include "r.h" |  | ||||||
| #include "tools.h" | #include "tools.h" | ||||||
| #include "utils.h" | #include "utils.h" | ||||||
| 
 | 
 | ||||||
| @ -12,8 +12,8 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <time.h> |  | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  | #include <time.h> | ||||||
| 
 | 
 | ||||||
| volatile sig_atomic_t sigint_count = 0; | volatile sig_atomic_t sigint_count = 0; | ||||||
| time_t first_sigint_time = 0; | time_t first_sigint_time = 0; | ||||||
| @ -29,263 +29,259 @@ static void repl(void); | |||||||
| static void init(void); | static void init(void); | ||||||
| static void handle_sigint(int sig); | static void handle_sigint(int sig); | ||||||
| 
 | 
 | ||||||
| char *get_env_string() { | char * get_env_string(){ | ||||||
|   FILE *fp = popen("env", "r"); |     FILE *fp = popen("env", "r"); | ||||||
|   if (fp == NULL) { |     if (fp == NULL) { | ||||||
|     perror("popen failed"); |         perror("popen failed"); | ||||||
|     return NULL; |         return NULL; | ||||||
|   } |     } | ||||||
| 
 | 
 | ||||||
|   size_t buffer_size = 1024; |     size_t buffer_size = 1024; | ||||||
|   size_t total_size = 0; |     size_t total_size = 0; | ||||||
|   char *output = malloc(buffer_size); |     char *output = malloc(buffer_size); | ||||||
|   if (output == NULL) { |     if (output == NULL) { | ||||||
|     perror("malloc failed"); |         perror("malloc failed"); | ||||||
|     pclose(fp); |  | ||||||
|     return NULL; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   size_t bytes_read; |  | ||||||
|   while ((bytes_read = fread(output + total_size, 1, buffer_size - total_size, |  | ||||||
|                              fp)) > 0) { |  | ||||||
|     total_size += bytes_read; |  | ||||||
|     if (total_size >= buffer_size) { |  | ||||||
|       buffer_size *= 2; |  | ||||||
|       char *temp = realloc(output, buffer_size); |  | ||||||
|       if (temp == NULL) { |  | ||||||
|         perror("realloc failed"); |  | ||||||
|         free(output); |  | ||||||
|         pclose(fp); |         pclose(fp); | ||||||
|         return NULL; |         return NULL; | ||||||
|       } |  | ||||||
|       output = temp; |  | ||||||
|     } |     } | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   // Null-terminate the output
 |     size_t bytes_read; | ||||||
|   output[total_size] = '\0'; |     while ((bytes_read = fread(output + total_size, 1, buffer_size - total_size, fp)) > 0) { | ||||||
|  |         total_size += bytes_read; | ||||||
|  |         if (total_size >= buffer_size) { | ||||||
|  |             buffer_size *= 2; | ||||||
|  |             char *temp = realloc(output, buffer_size); | ||||||
|  |             if (temp == NULL) { | ||||||
|  |                 perror("realloc failed"); | ||||||
|  |                 free(output); | ||||||
|  |                 pclose(fp); | ||||||
|  |                 return NULL; | ||||||
|  |             } | ||||||
|  |             output = temp; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|   pclose(fp); |     // Null-terminate the output
 | ||||||
|   return output; |     output[total_size] = '\0'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     pclose(fp); | ||||||
|  |     return output; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static char *get_prompt_from_stdin(char *prompt) { | static char *get_prompt_from_stdin(char *prompt) { | ||||||
|   int index = 0; |     int index = 0; | ||||||
|   int c; |     int c; | ||||||
|   while ((c = getchar()) != EOF) { |     while ((c = getchar()) != EOF) { | ||||||
|     prompt[index++] = (char)c; |         prompt[index++] = (char)c; | ||||||
|   } |     } | ||||||
|   prompt[index] = '\0'; |     prompt[index] = '\0'; | ||||||
|   return prompt; |     return prompt; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static char *get_prompt_from_args(int argc, char **argv) { | static char *get_prompt_from_args(int argc, char **argv) { | ||||||
|   char *prompt = malloc(10 * 1024 * 1024 + 1); |     char *prompt = malloc(10 * 1024 * 1024 + 1); | ||||||
|   char *system = malloc(1024 * 1024); |     char *system = malloc(1024 * 1024); | ||||||
|   if (!prompt || !system) { |     if (!prompt || !system) { | ||||||
|     fprintf(stderr, "Error: Memory allocation failed.\n"); |         fprintf(stderr, "Error: Memory allocation failed.\n"); | ||||||
|     free(prompt); |         free(prompt); | ||||||
|     free(system); |         free(system); | ||||||
|     return NULL; |         return NULL; | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   bool get_from_std_in = false; |  | ||||||
| 
 |  | ||||||
|   for (int i = 1; i < argc; i++) { |  | ||||||
|     if (strcmp(argv[i], "--stdin") == 0) { |  | ||||||
|       fprintf(stderr, "Reading from stdin.\n"); |  | ||||||
|       get_from_std_in = true; |  | ||||||
|     } else if (strcmp(argv[i], "--verbose") == 0) { |  | ||||||
|       is_verbose = true; |  | ||||||
|     } else if (strcmp(argv[i], "--py") == 0 && i + 1 < argc) { |  | ||||||
|       char *py_file_path = expand_home_directory(argv[++i]); |  | ||||||
|       fprintf(stderr, "Including \"%s\".\n", py_file_path); |  | ||||||
|       openai_include(py_file_path); |  | ||||||
|       free(py_file_path); |  | ||||||
|     } else if (strcmp(argv[i], "--free") == 0) { |  | ||||||
|       auth_free(); |  | ||||||
|     } else if (strcmp(argv[i], "--context") == 0 && i + 1 < argc) { |  | ||||||
|       char *context_file_path = argv[++i]; |  | ||||||
|       fprintf(stderr, "Including \"%s\".\n", context_file_path); |  | ||||||
|       openai_include(context_file_path); |  | ||||||
|     } else if (strcmp(argv[i], "--api") == 0) { |  | ||||||
|       API_MODE = true; |  | ||||||
|     } else if (strcmp(argv[i], "--nh") == 0) { |  | ||||||
|       SYNTAX_HIGHLIGHT_ENABLED = false; |  | ||||||
|       fprintf(stderr, "Syntax highlighting disabled.\n"); |  | ||||||
|     } else { |  | ||||||
|       strcat(system, argv[i]); |  | ||||||
|       strcat(system, (i < argc - 1) ? " " : "."); |  | ||||||
|     } |     } | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   if (get_from_std_in) { |     bool get_from_std_in = false; | ||||||
|     if (*system) |  | ||||||
|       openai_system(system); |  | ||||||
|     prompt = get_prompt_from_stdin(prompt); |  | ||||||
|   } else { |  | ||||||
|     free(prompt); |  | ||||||
|     prompt = system; |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   if (!*prompt) { |     for (int i = 1; i < argc; i++) { | ||||||
|     free(prompt); |         if (strcmp(argv[i], "--stdin") == 0) { | ||||||
|     return NULL; |             fprintf(stderr, "Reading from stdin.\n"); | ||||||
|   } |             get_from_std_in = true; | ||||||
|   return prompt; |         } else if (strcmp(argv[i], "--verbose") == 0) { | ||||||
|  |             is_verbose = true; | ||||||
|  |         } else if (strcmp(argv[i], "--py") == 0 && i + 1 < argc) { | ||||||
|  |             char *py_file_path = expand_home_directory(argv[++i]); | ||||||
|  |             fprintf(stderr, "Including \"%s\".\n", py_file_path); | ||||||
|  |             openai_include(py_file_path); | ||||||
|  |             free(py_file_path); | ||||||
|  |         } else if (strcmp(argv[i], "--free") == 0) { | ||||||
|  |             auth_free(); | ||||||
|  |         } else if (strcmp(argv[i], "--context") == 0 && i + 1 < argc) { | ||||||
|  |             char *context_file_path = argv[++i]; | ||||||
|  |             fprintf(stderr, "Including \"%s\".\n", context_file_path); | ||||||
|  |             openai_include(context_file_path); | ||||||
|  |         } else if (strcmp(argv[i], "--api") == 0) { | ||||||
|  |             API_MODE = true; | ||||||
|  |         } else if (strcmp(argv[i], "--nh") == 0) { | ||||||
|  |             SYNTAX_HIGHLIGHT_ENABLED = false; | ||||||
|  |             fprintf(stderr, "Syntax highlighting disabled.\n"); | ||||||
|  |         } else { | ||||||
|  |             strcat(system, argv[i]); | ||||||
|  |             strcat(system, (i < argc - 1) ? " " : "."); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (get_from_std_in) { | ||||||
|  |         if (*system) | ||||||
|  |             openai_system(system); | ||||||
|  |         prompt = get_prompt_from_stdin(prompt); | ||||||
|  |     } else { | ||||||
|  |         free(prompt); | ||||||
|  |         prompt = system; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!*prompt) { | ||||||
|  |         free(prompt); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |     return prompt; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool try_prompt(int argc, char *argv[]) { | static bool try_prompt(int argc, char *argv[]) { | ||||||
|   char *prompt = get_prompt_from_args(argc, argv); |     char *prompt = get_prompt_from_args(argc, argv); | ||||||
|   if (prompt) { |     if (prompt) { | ||||||
|     char *response = openai_chat("user", prompt); |         char *response = openai_chat("user", prompt); | ||||||
|     if (!response) { |         if (!response) { | ||||||
|       printf("Could not get response from server\n"); |             printf("Could not get response from server\n"); | ||||||
|       free(prompt); |             free(prompt); | ||||||
|       return false; |             return false; | ||||||
|  |         } | ||||||
|  |         render(response); | ||||||
|  |         free(response); | ||||||
|  |         free(prompt); | ||||||
|  |         return true; | ||||||
|     } |     } | ||||||
|     render(response); |     return false; | ||||||
|     free(response); |  | ||||||
|     free(prompt); |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
|   return false; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool openai_include(const char *path) { | static bool openai_include(const char *path) { | ||||||
|   char *file_content = read_file(path); |     char *file_content = read_file(path); | ||||||
|   if (!file_content) |     if (!file_content) | ||||||
|     return false; |         return false; | ||||||
| 
 | 
 | ||||||
|   openai_system(file_content); |     openai_system(file_content); | ||||||
|   free(file_content); |     free(file_content); | ||||||
|   return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void render(const char *content) { | static void render(const char *content) { | ||||||
|   if (SYNTAX_HIGHLIGHT_ENABLED) { |     if (SYNTAX_HIGHLIGHT_ENABLED) { | ||||||
|     parse_markdown_to_ansi(content); |         parse_markdown_to_ansi(content); | ||||||
|   } else { |     } else { | ||||||
|     printf("%s", content); |         printf("%s", content); | ||||||
|   } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void repl(void) { | static void repl(void) { | ||||||
|   line_init(); |     line_init(); | ||||||
|   char *line = NULL; |     char *line = NULL; | ||||||
| 
 | 
 | ||||||
|   while (true) { |     while (true) { | ||||||
|     line = line_read("> "); |         line = line_read("> "); | ||||||
|     if (!line || !*line) |         if (!line || !*line) | ||||||
|       continue; |             continue; | ||||||
| 
 | 
 | ||||||
|     if (!strncmp(line, "!dump", 5)) { |         if (!strncmp(line, "!dump", 5)) { | ||||||
|       printf("%s\n", message_json()); |             printf("%s\n", message_json()); | ||||||
|       continue; |             continue; | ||||||
|     } |         } | ||||||
|     if (!strncmp(line, "!verbose", 8)) { |         if (!strncmp(line, "!verbose", 8)) { | ||||||
|       is_verbose = !is_verbose; |             is_verbose = !is_verbose; | ||||||
|       fprintf(stderr, "%s\n", |             fprintf(stderr, "%s\n", is_verbose ? "Verbose mode enabled" : "Verbose mode disabled"); | ||||||
|               is_verbose ? "Verbose mode enabled" : "Verbose mode disabled"); |             continue; | ||||||
|       continue; |         } | ||||||
|     } |         if (line && *line != '\n') | ||||||
|     if (line && *line != '\n') |             line_add_history(line); | ||||||
|       line_add_history(line); |         if (!strncmp(line, "!tools", 6)) { | ||||||
|     if (!strncmp(line, "!tools", 6)) { |             printf("Available tools: %s\n", json_object_to_json_string(tools_descriptions())); | ||||||
|       printf("Available tools: %s\n", |             continue; | ||||||
|              json_object_to_json_string(tools_descriptions())); |         } | ||||||
|       continue; |         if (!strncmp(line, "!models", 7)) { | ||||||
|     } |             printf("Current model: %s\n", openai_fetch_models()); | ||||||
|     if (!strncmp(line, "!models", 7)) { |             continue; | ||||||
|       printf("Current model: %s\n", openai_fetch_models()); |         } | ||||||
|       continue; |         if (!strncmp(line, "!model", 6)) { | ||||||
|     } |             if (line[6] == ' ') { | ||||||
|     if (!strncmp(line, "!model", 6)) { |                 set_prompt_model(line + 7); | ||||||
|       if (line[6] == ' ') { |             } | ||||||
|         set_prompt_model(line + 7); |             printf("Current model: %s\n", get_prompt_model()); | ||||||
|       } |             continue; | ||||||
|       printf("Current model: %s\n", get_prompt_model()); |         } | ||||||
|       continue; |         if (!strncmp(line, "exit", 4)) | ||||||
|     } |             exit(0); | ||||||
|     if (!strncmp(line, "exit", 4)) | 
 | ||||||
|       exit(0); |         while (line && *line != '\n') { | ||||||
| 
 |             char *response = openai_chat("user", line); | ||||||
|     while (line && *line != '\n') { |             if (response) { | ||||||
|       char *response = openai_chat("user", line); |                 render(response); | ||||||
|       if (response) { |                 printf("\n"); | ||||||
|         render(response); |                 if (strstr(response, "_STEP_")) { | ||||||
|         printf("\n"); |                     line = "continue"; | ||||||
|         if (strstr(response, "_STEP_")) { |                 } else { | ||||||
|           line = "continue"; |                     line = NULL; | ||||||
|         } else { |                 } | ||||||
|           line = NULL; |                 free(response); | ||||||
|  |             } else { | ||||||
|  |                 exit(0); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         free(response); |  | ||||||
|       } else { |  | ||||||
|         exit(0); |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|   } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void init(void) { | static void init(void) { | ||||||
|   setbuf(stdout, NULL); |     setbuf(stdout, NULL); | ||||||
|   line_init(); |     line_init(); | ||||||
|   auth_init(); |     auth_init(); | ||||||
|   db_initialize(); |     db_initialize(); | ||||||
|   char *schema = db_get_schema(); |     char *schema = db_get_schema(); | ||||||
|   char payload[1024 * 1024] = {0}; |     char payload[1024 * 1024] = {0}; | ||||||
|   snprintf( |     snprintf(payload, sizeof(payload), | ||||||
|       payload, sizeof(payload), |             "# LOCAL DATABASE"  | ||||||
|       "# LOCAL DATABASE" |             "Your have a local database that you can mutate using the query tool and " | ||||||
|       "Your have a local database that you can mutate using the query tool and " |              "the get and set tool." | ||||||
|       "the get and set tool." |              "If you set a value using the tool, make sure that the key is stemmed and lowercased to prevent double entries." | ||||||
|       "If you set a value using the tool, make sure that the key is stemmed " |              "Dialect is sqlite. This is the schema in json format: %s. ", | ||||||
|       "and lowercased to prevent double entries." |              schema); | ||||||
|       "Dialect is sqlite. This is the schema in json format: %s. ", |     free(schema); | ||||||
|       schema); |     fprintf(stderr, "Loading... 📨"); | ||||||
|   free(schema); |     openai_system(payload); | ||||||
|   fprintf(stderr, "Loading... 📨"); |     char * env_system_message = get_env_system_message(); | ||||||
|   openai_system(payload); |     if(env_system_message && *env_system_message){ | ||||||
|   char *env_system_message = get_env_system_message(); |         openai_system(env_system_message); | ||||||
|   if (env_system_message && *env_system_message) { |         free(env_system_message); | ||||||
|     openai_system(env_system_message); |     } | ||||||
|     free(env_system_message); |     if (!openai_include(".rcontext.txt")) { | ||||||
|   } |         openai_include("~/.rcontext.txt"); | ||||||
|   if (!openai_include(".rcontext.txt")) { |     } | ||||||
|     openai_include("~/.rcontext.txt"); |     fprintf(stderr, "\r                          \r"); | ||||||
|   } |  | ||||||
|   fprintf(stderr, "\r                          \r"); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void handle_sigint(int sig) { | static void handle_sigint(int sig) { | ||||||
|   time_t current_time = time(NULL); |     time_t current_time = time(NULL); | ||||||
|   printf("\n"); |     printf("\n"); | ||||||
|   if (sigint_count == 0) { |     if (sigint_count == 0) { | ||||||
|     first_sigint_time = current_time; |         first_sigint_time = current_time; | ||||||
|     sigint_count++; |         sigint_count++; | ||||||
|   } else { |  | ||||||
|     if (difftime(current_time, first_sigint_time) <= 1) { |  | ||||||
|       exit(0); |  | ||||||
|     } else { |     } else { | ||||||
|       sigint_count = 1; |         if (difftime(current_time, first_sigint_time) <= 1) { | ||||||
|       first_sigint_time = current_time; |             exit(0); | ||||||
|  |         } else { | ||||||
|  |             sigint_count = 1; | ||||||
|  |             first_sigint_time = current_time; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|   } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   signal(SIGINT, handle_sigint); |     signal(SIGINT, handle_sigint); | ||||||
| 
 | 
 | ||||||
|   init(); |     init(); | ||||||
|   char *env_string = get_env_string(); |     char * env_string = get_env_string(); | ||||||
|   if (env_string && *env_string) { |     if(env_string && *env_string){ | ||||||
|     openai_system(env_string); |         openai_system(env_string); | ||||||
|     free(env_string); |         free(env_string); | ||||||
|   } |     } | ||||||
|   if (try_prompt(argc, argv)) |     if (try_prompt(argc, argv)) | ||||||
|  |         return 0; | ||||||
|  | 
 | ||||||
|  |     repl(); | ||||||
|     return 0; |     return 0; | ||||||
| 
 |  | ||||||
|   repl(); |  | ||||||
|   return 0; |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										354
									
								
								markdown.h
									
									
									
									
									
								
							
							
						
						
									
										354
									
								
								markdown.h
									
									
									
									
									
								
							| @ -1,30 +1,45 @@ | |||||||
| #include <ctype.h> | // Written by retoor@molodetz.nl
 | ||||||
|  | 
 | ||||||
|  | // This program provides functionality to highlight the keywords in source code
 | ||||||
|  | // using ANSI color formatting and convert Markdown syntax into ANSI-colored
 | ||||||
|  | // text output.
 | ||||||
|  | 
 | ||||||
|  | // Uses standard C libraries: <stdio.h>, <string.h>. Also utilizes ANSI escape
 | ||||||
|  | // codes for text formatting.
 | ||||||
|  | 
 | ||||||
|  | // MIT License:
 | ||||||
|  | // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||||
|  | // of this software and associated documentation files (the "Software"), to deal
 | ||||||
|  | // in the Software without restriction, including without limitation the rights
 | ||||||
|  | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||||
|  | // copies of the Software, and to permit persons to whom the Software is
 | ||||||
|  | // furnished to do so, subject to the following conditions:
 | ||||||
|  | //
 | ||||||
|  | // The above copyright notice and this permission notice shall be included in
 | ||||||
|  | // all copies or substantial portions of the Software.
 | ||||||
|  | //
 | ||||||
|  | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||||
|  | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||||
|  | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||||
|  | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||||
|  | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||||
|  | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | ||||||
|  | // SOFTWARE.
 | ||||||
|  | 
 | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| 
 | 
 | ||||||
| // --- ANSI Escape Codes ---
 |  | ||||||
| #define RESET "\033[0m" | #define RESET "\033[0m" | ||||||
| #define BOLD "\033[1m" | #define BOLD "\033[1m" | ||||||
| #define ITALIC "\033[3m" | #define ITALIC "\033[3m" | ||||||
| #define STRIKETHROUGH "\033[9m" |  | ||||||
| 
 |  | ||||||
| #define FG_YELLOW "\033[33m" | #define FG_YELLOW "\033[33m" | ||||||
| #define FG_BLUE "\033[34m" | #define FG_BLUE "\033[34m" | ||||||
| #define FG_CYAN "\033[36m" | #define FG_CYAN "\033[36m" | ||||||
| #define FG_MAGENTA "\033[35m" |  | ||||||
| 
 | 
 | ||||||
| #define BG_YELLOW_FG_BLACK "\033[43;30m" |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * @brief Checks if a given word is a programming language keyword. |  | ||||||
|  * * @param word The word to check. |  | ||||||
|  * @return int 1 if it's a keyword, 0 otherwise. |  | ||||||
|  */ |  | ||||||
| int is_keyword(const char *word) { | int is_keyword(const char *word) { | ||||||
|   // A comprehensive list of keywords from various popular languages.
 | 
 | ||||||
|   const char *keywords[] = { |   const char *keywords[] = { | ||||||
|       // C keywords
 |  | ||||||
|       "int", "float", "double", "char", "void", "if", "else", "while", "for", |       "int", "float", "double", "char", "void", "if", "else", "while", "for", | ||||||
|       "return", "struct", "printf", |       "return", "struct", "printf", | ||||||
|       // Rust keywords
 |       // Rust keywords
 | ||||||
| @ -60,38 +75,33 @@ int is_keyword(const char *word) { | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * @brief Applies basic syntax highlighting to a string of code. |  | ||||||
|  * * @param code The code string to highlight. |  | ||||||
|  */ |  | ||||||
| void highlight_code(const char *code) { | void highlight_code(const char *code) { | ||||||
|   const char *ptr = code; |   const char *ptr = code; | ||||||
|   char buffer[4096]; |   char buffer[4096]; | ||||||
|   size_t index = 0; |   size_t index = 0; | ||||||
| 
 | 
 | ||||||
|   while (*ptr) { |   while (*ptr) { | ||||||
|     // Highlight keywords
 |     if ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') || | ||||||
|     if (isalpha((unsigned char)*ptr) || *ptr == '_') { |         (*ptr == '_')) { | ||||||
|       while (isalnum((unsigned char)*ptr) || *ptr == '_') { |       while ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') || | ||||||
|  |              (*ptr >= '0' && *ptr <= '9') || (*ptr == '_')) { | ||||||
|         buffer[index++] = *ptr++; |         buffer[index++] = *ptr++; | ||||||
|       } |       } | ||||||
|       buffer[index] = '\0'; |       buffer[index] = 0; | ||||||
| 
 | 
 | ||||||
|       if (is_keyword(buffer)) { |       if (is_keyword(buffer)) { | ||||||
|         printf(FG_BLUE "%s" RESET FG_YELLOW, buffer); |         printf(FG_BLUE "%s" RESET, buffer); | ||||||
|       } else { |       } else { | ||||||
|         printf("%s", buffer); |         printf("%s", buffer); | ||||||
|       } |       } | ||||||
|       index = 0; |       index = 0; | ||||||
|       // Highlight numbers
 |     } else if (*ptr >= '0' && *ptr <= '9') { | ||||||
|     } else if (isdigit((unsigned char)*ptr)) { |       while (*ptr >= '0' && *ptr <= '9') { | ||||||
|       while (isdigit((unsigned char)*ptr)) { |  | ||||||
|         buffer[index++] = *ptr++; |         buffer[index++] = *ptr++; | ||||||
|       } |       } | ||||||
|       buffer[index] = '\0'; |       buffer[index] = 0; | ||||||
|       printf(FG_CYAN "%s" RESET FG_YELLOW, buffer); |       printf(FG_CYAN "%s" RESET, buffer); | ||||||
|       index = 0; |       index = 0; | ||||||
|       // Print other characters as-is
 |  | ||||||
|     } else { |     } else { | ||||||
|       putchar(*ptr); |       putchar(*ptr); | ||||||
|       ptr++; |       ptr++; | ||||||
| @ -99,253 +109,93 @@ void highlight_code(const char *code) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * @brief Parses a Markdown string and prints it to the console with ANSI color |  | ||||||
|  * codes. |  | ||||||
|  * |  | ||||||
|  * This version supports a wide range of Markdown features, including: |  | ||||||
|  * - Headers (H1-H6) |  | ||||||
|  * - Bold (**, __) and Italic (*, _) text |  | ||||||
|  * - Strikethrough (~~) and Highlight (==) |  | ||||||
|  * - Blockquotes (>), Nested Ordered (1.) and Unordered lists (*, -, +) |  | ||||||
|  * - Inline code (`) and full code blocks (```) with syntax highlighting |  | ||||||
|  * - Links ([text](url)) and Horizontal rules (---, ***) |  | ||||||
|  * * @param markdown The raw Markdown string to parse. |  | ||||||
|  */ |  | ||||||
| void parse_markdown_to_ansi(const char *markdown) { | void parse_markdown_to_ansi(const char *markdown) { | ||||||
|   const char *ptr = markdown; |   const char *ptr = markdown; | ||||||
|   bool is_start_of_line = true; |   bool inside_code = false; | ||||||
| 
 | 
 | ||||||
|   while (*ptr) { |   while (*ptr) { | ||||||
|     // --- Code Blocks (```) ---
 |     if (*ptr == '`' && *(ptr + 1) != '`') { | ||||||
|     if (is_start_of_line && strncmp(ptr, "```", 3) == 0) { |       inside_code = !inside_code; | ||||||
|       ptr += 3; |       if (inside_code) { | ||||||
|       while (*ptr && *ptr != '\n') |  | ||||||
|         ptr++; |  | ||||||
|       if (*ptr) |  | ||||||
|         ptr++; |  | ||||||
| 
 |  | ||||||
|       const char *code_start = ptr; |  | ||||||
|       const char *code_end = strstr(code_start, "```"); |  | ||||||
| 
 |  | ||||||
|       if (code_end) { |  | ||||||
|         char block_buffer[code_end - code_start + 1]; |  | ||||||
|         strncpy(block_buffer, code_start, code_end - code_start); |  | ||||||
|         block_buffer[code_end - code_start] = '\0'; |  | ||||||
| 
 |  | ||||||
|         printf(FG_YELLOW); |         printf(FG_YELLOW); | ||||||
|         highlight_code(block_buffer); |  | ||||||
|         printf(RESET); |  | ||||||
| 
 |  | ||||||
|         ptr = code_end + 3; |  | ||||||
|         if (*ptr == '\n') |  | ||||||
|           ptr++; |  | ||||||
|         is_start_of_line = true; |  | ||||||
|         continue; |  | ||||||
|       } else { |       } else { | ||||||
|         printf(FG_YELLOW); |  | ||||||
|         highlight_code(code_start); |  | ||||||
|         printf(RESET); |         printf(RESET); | ||||||
|  |       } | ||||||
|  |       ptr++; | ||||||
|  |       continue; | ||||||
|  |     } else if (!strncmp(ptr, "```", 3)) { | ||||||
|  |       inside_code = !inside_code; | ||||||
|  |       if (inside_code) { | ||||||
|  |         ptr = strstr(ptr, "\n") + 1; | ||||||
|  |       } else { | ||||||
|  |         ptr += 3; | ||||||
|  |       } | ||||||
|  |       if (*ptr == '\0') { | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // --- Block-level Elements (checked at the start of a line) ---
 |     if (inside_code) { | ||||||
|     if (is_start_of_line) { |       char code_buffer[1024 * 1024] = {0}; | ||||||
|       const char *line_start_ptr = ptr; |       ; | ||||||
|       int indent_level = 0; |       size_t index = 0; | ||||||
|       while (*ptr == ' ') { |  | ||||||
|         indent_level++; |  | ||||||
|         ptr++; |  | ||||||
|       } |  | ||||||
| 
 | 
 | ||||||
|       bool block_processed = true; |       while (*ptr && *ptr != '`') { | ||||||
|       if (strncmp(ptr, "###### ", 7) == 0) { |         code_buffer[index++] = *ptr++; | ||||||
|         printf(BOLD FG_YELLOW); |         if (*ptr == '\n' || *ptr == ' ' || *ptr == '\t' || *ptr == '.') { | ||||||
|         ptr += 7; |           code_buffer[index++] = 0; | ||||||
|       } else if (strncmp(ptr, "##### ", 6) == 0) { |           highlight_code(code_buffer); | ||||||
|         printf(BOLD FG_YELLOW); |           index = 0; | ||||||
|         ptr += 6; |         } | ||||||
|       } else if (strncmp(ptr, "#### ", 5) == 0) { |       } | ||||||
|         printf(BOLD FG_YELLOW); |       code_buffer[index] = 0; | ||||||
|         ptr += 5; |       if (index) { | ||||||
|  |         highlight_code(code_buffer); | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       if (strncmp(ptr, "**", 2) == 0) { | ||||||
|  |         printf(BOLD); | ||||||
|  |         ptr += 2; | ||||||
|  |         while (*ptr && strncmp(ptr, "**", 2) != 0) { | ||||||
|  |           putchar(*ptr++); | ||||||
|  |         } | ||||||
|  |         if (*ptr == '*' && *(ptr + 1) == '*') | ||||||
|  |           ptr += 2; | ||||||
|  |         printf(RESET); | ||||||
|  |       } else if (*ptr == '*' && (ptr == markdown || *(ptr - 1) != '*')) { | ||||||
|  |         printf(ITALIC); | ||||||
|  |         ptr++; | ||||||
|  |         while (*ptr && *ptr != '*') { | ||||||
|  |           putchar(*ptr++); | ||||||
|  |         } | ||||||
|  |         if (*ptr == '*') | ||||||
|  |           ptr++; | ||||||
|  |         printf(RESET); | ||||||
|       } else if (strncmp(ptr, "### ", 4) == 0) { |       } else if (strncmp(ptr, "### ", 4) == 0) { | ||||||
|         printf(BOLD FG_YELLOW); |         printf(BOLD FG_YELLOW); | ||||||
|         ptr += 4; |         ptr += 4; | ||||||
|  |         while (*ptr && *ptr != '\n') { | ||||||
|  |           putchar(*ptr++); | ||||||
|  |         } | ||||||
|  |         printf(RESET "\n"); | ||||||
|       } else if (strncmp(ptr, "## ", 3) == 0) { |       } else if (strncmp(ptr, "## ", 3) == 0) { | ||||||
|         printf(BOLD FG_YELLOW); |         printf(BOLD FG_YELLOW); | ||||||
|         ptr += 3; |         ptr += 3; | ||||||
|  |         while (*ptr && *ptr != '\n') { | ||||||
|  |           putchar(*ptr++); | ||||||
|  |         } | ||||||
|  |         printf(RESET "\n"); | ||||||
|       } else if (strncmp(ptr, "# ", 2) == 0) { |       } else if (strncmp(ptr, "# ", 2) == 0) { | ||||||
|         printf(BOLD FG_YELLOW); |         printf(BOLD FG_YELLOW); | ||||||
|         ptr += 2; |         ptr += 2; | ||||||
|       } else if ((strncmp(ptr, "---", 3) == 0 || strncmp(ptr, "***", 3) == 0) && |         while (*ptr && *ptr != '\n') { | ||||||
|                  (*(ptr + 3) == '\n' || *(ptr + 3) == '\0')) { |  | ||||||
|         printf(FG_CYAN "───────────────────────────────────────────────────────" |  | ||||||
|                        "──────────" RESET "\n"); |  | ||||||
|         ptr += 3; |  | ||||||
|         if (*ptr == '\n') |  | ||||||
|           ptr++; |  | ||||||
|         is_start_of_line = true; |  | ||||||
|         continue; |  | ||||||
|       } else if (strncmp(ptr, "> ", 2) == 0) { |  | ||||||
|         for (int i = 0; i < indent_level; i++) |  | ||||||
|           putchar(' '); |  | ||||||
|         printf(ITALIC FG_CYAN "▎ " RESET); |  | ||||||
|         ptr += 2; |  | ||||||
|         is_start_of_line = false; |  | ||||||
|         continue; |  | ||||||
|       } else if ((*ptr == '*' || *ptr == '-' || *ptr == '+') && |  | ||||||
|                  *(ptr + 1) == ' ') { |  | ||||||
|         for (int i = 0; i < indent_level; i++) |  | ||||||
|           putchar(' '); |  | ||||||
|         printf(FG_MAGENTA "• " RESET); |  | ||||||
|         ptr += 2; |  | ||||||
|         is_start_of_line = false; |  | ||||||
|         continue; |  | ||||||
|       } else { |  | ||||||
|         const char *temp_ptr = ptr; |  | ||||||
|         while (isdigit((unsigned char)*temp_ptr)) |  | ||||||
|           temp_ptr++; |  | ||||||
|         if (temp_ptr > ptr && *temp_ptr == '.' && *(temp_ptr + 1) == ' ') { |  | ||||||
|           for (int i = 0; i < indent_level; i++) |  | ||||||
|             putchar(' '); |  | ||||||
|           printf(FG_MAGENTA); |  | ||||||
|           fwrite(ptr, 1, (temp_ptr - ptr) + 1, stdout); |  | ||||||
|           printf(" " RESET); |  | ||||||
|           ptr = temp_ptr + 2; |  | ||||||
|           is_start_of_line = false; |  | ||||||
|           continue; |  | ||||||
|         } else { |  | ||||||
|           block_processed = false; |  | ||||||
|           ptr = line_start_ptr; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       if (block_processed) { |  | ||||||
|         while (*ptr && *ptr != '\n') |  | ||||||
|           putchar(*ptr++); |           putchar(*ptr++); | ||||||
|         printf(RESET "\n"); |  | ||||||
|         if (*ptr == '\n') |  | ||||||
|           ptr++; |  | ||||||
|         is_start_of_line = true; |  | ||||||
|         continue; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // --- Inline Elements (order is important) ---
 |  | ||||||
|     if (strncmp(ptr, "***", 3) == 0 || strncmp(ptr, "___", 3) == 0) { |  | ||||||
|       const char *marker = strncmp(ptr, "***", 3) == 0 ? "***" : "___"; |  | ||||||
|       printf(BOLD ITALIC); |  | ||||||
|       ptr += 3; |  | ||||||
|       const char *end = strstr(ptr, marker); |  | ||||||
|       if (end) { |  | ||||||
|         fwrite(ptr, 1, end - ptr, stdout); |  | ||||||
|         ptr = end + 3; |  | ||||||
|       } else { |  | ||||||
|         fputs(ptr, stdout); |  | ||||||
|         ptr += strlen(ptr); |  | ||||||
|       } |  | ||||||
|       printf(RESET); |  | ||||||
|       continue; |  | ||||||
|     } |  | ||||||
|     if (strncmp(ptr, "**", 2) == 0 || strncmp(ptr, "__", 2) == 0) { |  | ||||||
|       const char *marker = strncmp(ptr, "**", 2) == 0 ? "**" : "__"; |  | ||||||
|       printf(BOLD); |  | ||||||
|       ptr += 2; |  | ||||||
|       const char *end = strstr(ptr, marker); |  | ||||||
|       if (end) { |  | ||||||
|         fwrite(ptr, 1, end - ptr, stdout); |  | ||||||
|         ptr = end + 2; |  | ||||||
|       } else { |  | ||||||
|         fputs(ptr, stdout); |  | ||||||
|         ptr += strlen(ptr); |  | ||||||
|       } |  | ||||||
|       printf(RESET); |  | ||||||
|       continue; |  | ||||||
|     } |  | ||||||
|     if ((*ptr == '*' || *ptr == '_') && !isspace(*(ptr - 1)) && |  | ||||||
|         !isspace(*(ptr + 1))) { |  | ||||||
|       char marker = *ptr; |  | ||||||
|       printf(ITALIC); |  | ||||||
|       ptr++; |  | ||||||
|       const char *start = ptr; |  | ||||||
|       while (*ptr && *ptr != marker) |  | ||||||
|         ptr++; |  | ||||||
|       if (*ptr == marker) { |  | ||||||
|         fwrite(start, 1, ptr - start, stdout); |  | ||||||
|         ptr++; |  | ||||||
|       } else { |  | ||||||
|         putchar(marker); |  | ||||||
|         ptr = start; |  | ||||||
|       } |  | ||||||
|       printf(RESET); |  | ||||||
|       continue; |  | ||||||
|     } |  | ||||||
|     if (strncmp(ptr, "~~", 2) == 0) { |  | ||||||
|       printf(STRIKETHROUGH); |  | ||||||
|       ptr += 2; |  | ||||||
|       const char *end = strstr(ptr, "~~"); |  | ||||||
|       if (end) { |  | ||||||
|         fwrite(ptr, 1, end - ptr, stdout); |  | ||||||
|         ptr = end + 2; |  | ||||||
|       } else { |  | ||||||
|         fputs(ptr, stdout); |  | ||||||
|         ptr += strlen(ptr); |  | ||||||
|       } |  | ||||||
|       printf(RESET); |  | ||||||
|       continue; |  | ||||||
|     } |  | ||||||
|     if (strncmp(ptr, "==", 2) == 0) { |  | ||||||
|       printf(BG_YELLOW_FG_BLACK); |  | ||||||
|       ptr += 2; |  | ||||||
|       const char *end = strstr(ptr, "=="); |  | ||||||
|       if (end) { |  | ||||||
|         fwrite(ptr, 1, end - ptr, stdout); |  | ||||||
|         ptr = end + 2; |  | ||||||
|       } else { |  | ||||||
|         fputs(ptr, stdout); |  | ||||||
|         ptr += strlen(ptr); |  | ||||||
|       } |  | ||||||
|       printf(RESET); |  | ||||||
|       continue; |  | ||||||
|     } |  | ||||||
|     if (*ptr == '`' && *(ptr + 1) != '`') { |  | ||||||
|       printf(FG_YELLOW); |  | ||||||
|       ptr++; |  | ||||||
|       const char *start = ptr; |  | ||||||
|       while (*ptr && *ptr != '`') |  | ||||||
|         ptr++; |  | ||||||
|       fwrite(start, 1, ptr - start, stdout); |  | ||||||
|       if (*ptr == '`') |  | ||||||
|         ptr++; |  | ||||||
|       printf(RESET); |  | ||||||
|       continue; |  | ||||||
|     } |  | ||||||
|     if (*ptr == '[') { |  | ||||||
|       const char *text_start = ptr + 1; |  | ||||||
|       const char *text_end = strchr(text_start, ']'); |  | ||||||
|       if (text_end && *(text_end + 1) == '(') { |  | ||||||
|         const char *url_start = text_end + 2; |  | ||||||
|         const char *url_end = strchr(url_start, ')'); |  | ||||||
|         if (url_end) { |  | ||||||
|           printf(FG_BLUE); |  | ||||||
|           fwrite(text_start, 1, text_end - text_start, stdout); |  | ||||||
|           printf(RESET " ("); |  | ||||||
|           printf(ITALIC FG_CYAN); |  | ||||||
|           fwrite(url_start, 1, url_end - url_start, stdout); |  | ||||||
|           printf(RESET ")"); |  | ||||||
|           ptr = url_end + 1; |  | ||||||
|           continue; |  | ||||||
|         } |         } | ||||||
|  |         printf(RESET "\n"); | ||||||
|  |       } else { | ||||||
|  |         putchar(*ptr); | ||||||
|  |         ptr++; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     // --- Default Character ---
 |  | ||||||
|     if (*ptr == '\n') { |  | ||||||
|       is_start_of_line = true; |  | ||||||
|     } else if (!isspace((unsigned char)*ptr)) { |  | ||||||
|       is_start_of_line = false; |  | ||||||
|     } |  | ||||||
|     putchar(*ptr); |  | ||||||
|     ptr++; |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								messages.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								messages.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										43
									
								
								r.h
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								r.h
									
									
									
									
									
								
							| @ -32,30 +32,31 @@ char *_model = NULL; | |||||||
| #define DB_FILE "~/.r.db" | #define DB_FILE "~/.r.db" | ||||||
| #define PROMPT_TEMPERATURE 0.1 | #define PROMPT_TEMPERATURE 0.1 | ||||||
| 
 | 
 | ||||||
| bool use_tools() { | 
 | ||||||
|   if (getenv("R_USE_TOOLS") != NULL) { | bool use_tools(){ | ||||||
|     const char *value = getenv("R_USE_TOOLS"); |     if(getenv("R_USE_TOOLS") != NULL){ | ||||||
|     if (!strcmp(value, "true")) { |         const char *value = getenv("R_USE_TOOLS"); | ||||||
|       return true; |         if (!strcmp(value, "true")) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         if (!strcmp(value, "false")) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (!strcmp(value, "1")) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         if (!strcmp(value, "0")) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     if (!strcmp(value, "false")) { |     return true; | ||||||
|       return false; |  | ||||||
|     } |  | ||||||
|     if (!strcmp(value, "1")) { |  | ||||||
|       return true; |  | ||||||
|     } |  | ||||||
|     if (!strcmp(value, "0")) { |  | ||||||
|       return false; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return true; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char *get_env_system_message() { | char * get_env_system_message(){ | ||||||
|   if (getenv("R_SYSTEM_MESSAGE") != NULL) { |     if (getenv("R_SYSTEM_MESSAGE") != NULL) { | ||||||
|     return strdup(getenv("R_SYSTEM_MESSAGE")); |         return strdup(getenv("R_SYSTEM_MESSAGE")); | ||||||
|   } |     } | ||||||
|   return NULL; |     return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool get_use_strict() { | bool get_use_strict() { | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								r.png
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								r.png
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB | 
							
								
								
									
										0
									
								
								screenshot1.png
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								screenshot1.png
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB | 
							
								
								
									
										213
									
								
								tools.h
									
									
									
									
									
								
							
							
						
						
									
										213
									
								
								tools.h
									
									
									
									
									
								
							| @ -56,6 +56,7 @@ struct json_object *tool_description_rag_chunk(); | |||||||
| char *tool_function_rag_search(char *query, int top_k); | char *tool_function_rag_search(char *query, int top_k); | ||||||
| char *tool_function_rag_chunk(char *file_path); | char *tool_function_rag_chunk(char *file_path); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| char *tool_function_python_execute(char *source_code); | char *tool_function_python_execute(char *source_code); | ||||||
| 
 | 
 | ||||||
| struct json_object *tools_descriptions() { | struct json_object *tools_descriptions() { | ||||||
| @ -65,7 +66,7 @@ struct json_object *tools_descriptions() { | |||||||
|   json_object_array_add(root, tool_description_directory_glob()); |   json_object_array_add(root, tool_description_directory_glob()); | ||||||
|   json_object_array_add(root, tool_description_read_file()); |   json_object_array_add(root, tool_description_read_file()); | ||||||
|   json_object_array_add(root, tool_description_write_file()); |   json_object_array_add(root, tool_description_write_file()); | ||||||
|   // json_object_array_add(root, tool_description_directory_rglob());
 |   //json_object_array_add(root, tool_description_directory_rglob());
 | ||||||
|   json_object_array_add(root, tool_description_linux_terminal_interactive()); |   json_object_array_add(root, tool_description_linux_terminal_interactive()); | ||||||
|   json_object_array_add(root, tool_description_index_source_directory()); |   json_object_array_add(root, tool_description_index_source_directory()); | ||||||
|   json_object_array_add(root, tool_description_chdir()); |   json_object_array_add(root, tool_description_chdir()); | ||||||
| @ -423,88 +424,81 @@ char *tool_function_linux_terminal_interactive(char *command) { | |||||||
| 
 | 
 | ||||||
| // ---- PYTHON EXECUTE TOOL ----
 | // ---- PYTHON EXECUTE TOOL ----
 | ||||||
| char *tool_function_python_execute(char *source_code) { | char *tool_function_python_execute(char *source_code) { | ||||||
|   char tmp_file[] = "/tmp/r_python_tool_XXXXXX.py"; |     char tmp_file[] = "/tmp/r_python_tool_XXXXXX.py"; | ||||||
|   int fd = mkstemps(tmp_file, 3); // 3 for ".py"
 |     int fd = mkstemps(tmp_file, 3); // 3 for ".py"
 | ||||||
|   if (fd == -1) { |     if (fd == -1) { | ||||||
|     return strdup("Failed to create temporary file for Python code."); |         return strdup("Failed to create temporary file for Python code."); | ||||||
|   } |  | ||||||
|   FILE *fp = fdopen(fd, "w"); |  | ||||||
|   if (!fp) { |  | ||||||
|     close(fd); |  | ||||||
|     return strdup("Failed to open temporary file for writing."); |  | ||||||
|   } |  | ||||||
|   fwrite(source_code, 1, strlen(source_code), fp); |  | ||||||
|   fclose(fp); |  | ||||||
| 
 |  | ||||||
|   char command[4096]; |  | ||||||
|   snprintf(command, sizeof(command), "python3 '%s' 2>&1", tmp_file); |  | ||||||
| 
 |  | ||||||
|   FILE *proc = popen(command, "r"); |  | ||||||
|   if (!proc) { |  | ||||||
|     unlink(tmp_file); |  | ||||||
|     return strdup("Failed to execute python3."); |  | ||||||
|   } |  | ||||||
|   char buffer[1024]; |  | ||||||
|   size_t total = 0; |  | ||||||
|   char *output = NULL; |  | ||||||
|   while (fgets(buffer, sizeof(buffer), proc)) { |  | ||||||
|     size_t len = strlen(buffer); |  | ||||||
|     char *new_output = realloc(output, total + len + 1); |  | ||||||
|     if (!new_output) { |  | ||||||
|       free(output); |  | ||||||
|       pclose(proc); |  | ||||||
|       unlink(tmp_file); |  | ||||||
|       return strdup("Memory allocation failed."); |  | ||||||
|     } |     } | ||||||
|     output = new_output; |     FILE *fp = fdopen(fd, "w"); | ||||||
|     strcpy(output + total, buffer); |     if (!fp) { | ||||||
|     total += len; |         close(fd); | ||||||
|   } |         return strdup("Failed to open temporary file for writing."); | ||||||
|   if (output) |     } | ||||||
|     output[total] = 0; |     fwrite(source_code, 1, strlen(source_code), fp); | ||||||
|   else |     fclose(fp); | ||||||
|     output = strdup(""); | 
 | ||||||
|   pclose(proc); |     char command[4096]; | ||||||
|   unlink(tmp_file); |     snprintf(command, sizeof(command), "python3 '%s' 2>&1", tmp_file); | ||||||
|   return output; | 
 | ||||||
|  |     FILE *proc = popen(command, "r"); | ||||||
|  |     if (!proc) { | ||||||
|  |         unlink(tmp_file); | ||||||
|  |         return strdup("Failed to execute python3."); | ||||||
|  |     } | ||||||
|  |     char buffer[1024]; | ||||||
|  |     size_t total = 0; | ||||||
|  |     char *output = NULL; | ||||||
|  |     while (fgets(buffer, sizeof(buffer), proc)) { | ||||||
|  |         size_t len = strlen(buffer); | ||||||
|  |         char *new_output = realloc(output, total + len + 1); | ||||||
|  |         if (!new_output) { | ||||||
|  |             free(output); | ||||||
|  |             pclose(proc); | ||||||
|  |             unlink(tmp_file); | ||||||
|  |             return strdup("Memory allocation failed."); | ||||||
|  |         } | ||||||
|  |         output = new_output; | ||||||
|  |         strcpy(output + total, buffer); | ||||||
|  |         total += len; | ||||||
|  |     } | ||||||
|  |     if (output) | ||||||
|  |         output[total] = 0; | ||||||
|  |     else | ||||||
|  |         output = strdup(""); | ||||||
|  |     pclose(proc); | ||||||
|  |     unlink(tmp_file); | ||||||
|  |     return output; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct json_object *tool_description_python_execute() { | struct json_object *tool_description_python_execute() { | ||||||
|   struct json_object *root = json_object_new_object(); |     struct json_object *root = json_object_new_object(); | ||||||
|   json_object_object_add(root, "type", json_object_new_string("function")); |     json_object_object_add(root, "type", json_object_new_string("function")); | ||||||
| 
 | 
 | ||||||
|   struct json_object *function = json_object_new_object(); |     struct json_object *function = json_object_new_object(); | ||||||
|   json_object_object_add(function, "name", |     json_object_object_add(function, "name", json_object_new_string("python_execute")); | ||||||
|                          json_object_new_string("python_execute")); |     json_object_object_add(function, "description", json_object_new_string("Executes Python source code using the python3 interpreter and returns stdout/stderr.")); | ||||||
|   json_object_object_add( |  | ||||||
|       function, "description", |  | ||||||
|       json_object_new_string("Executes Python source code using the python3 " |  | ||||||
|                              "interpreter and returns stdout/stderr.")); |  | ||||||
| 
 | 
 | ||||||
|   struct json_object *parameters = json_object_new_object(); |     struct json_object *parameters = json_object_new_object(); | ||||||
|   json_object_object_add(parameters, "type", json_object_new_string("object")); |     json_object_object_add(parameters, "type", json_object_new_string("object")); | ||||||
| 
 | 
 | ||||||
|   struct json_object *properties = json_object_new_object(); |     struct json_object *properties = json_object_new_object(); | ||||||
|   struct json_object *source = json_object_new_object(); |     struct json_object *source = json_object_new_object(); | ||||||
|   json_object_object_add(source, "type", json_object_new_string("string")); |     json_object_object_add(source, "type", json_object_new_string("string")); | ||||||
|   json_object_object_add( |     json_object_object_add(source, "description", json_object_new_string("Python source code to execute.")); | ||||||
|       source, "description", |     json_object_object_add(properties, "source", source); | ||||||
|       json_object_new_string("Python source code to execute.")); |  | ||||||
|   json_object_object_add(properties, "source", source); |  | ||||||
| 
 | 
 | ||||||
|   json_object_object_add(parameters, "properties", properties); |     json_object_object_add(parameters, "properties", properties); | ||||||
| 
 | 
 | ||||||
|   struct json_object *required = json_object_new_array(); |     struct json_object *required = json_object_new_array(); | ||||||
|   json_object_array_add(required, json_object_new_string("source")); |     json_object_array_add(required, json_object_new_string("source")); | ||||||
|   json_object_object_add(parameters, "required", required); |     json_object_object_add(parameters, "required", required); | ||||||
| 
 | 
 | ||||||
|   json_object_object_add(parameters, "additionalProperties", |     json_object_object_add(parameters, "additionalProperties", json_object_new_boolean(0)); | ||||||
|                          json_object_new_boolean(0)); |     json_object_object_add(function, "parameters", parameters); | ||||||
|   json_object_object_add(function, "parameters", parameters); |  | ||||||
| 
 | 
 | ||||||
|   json_object_object_add(root, "function", function); |     json_object_object_add(root, "function", function); | ||||||
| 
 | 
 | ||||||
|   return root; |     return root; | ||||||
| } | } | ||||||
| // ---- END PYTHON EXECUTE TOOL ----
 | // ---- END PYTHON EXECUTE TOOL ----
 | ||||||
| 
 | 
 | ||||||
| @ -652,10 +646,9 @@ struct json_object *tool_description_linux_terminal_interactive() { | |||||||
|   struct json_object *properties = json_object_new_object(); |   struct json_object *properties = json_object_new_object(); | ||||||
|   struct json_object *path = json_object_new_object(); |   struct json_object *path = json_object_new_object(); | ||||||
|   json_object_object_add(path, "type", json_object_new_string("string")); |   json_object_object_add(path, "type", json_object_new_string("string")); | ||||||
|   json_object_object_add( |   json_object_object_add(path, "description", | ||||||
|       path, "description", |                          json_object_new_string( | ||||||
|       json_object_new_string( |                              "Executable with parameters to execute interactively.")); | ||||||
|           "Executable with parameters to execute interactively.")); |  | ||||||
|   json_object_object_add(properties, "command", path); |   json_object_object_add(properties, "command", path); | ||||||
| 
 | 
 | ||||||
|   json_object_object_add(parameters, "properties", properties); |   json_object_object_add(parameters, "properties", properties); | ||||||
| @ -823,9 +816,9 @@ struct json_object *tool_description_write_file() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char *tool_function_index_source_directory(char *path) { | char *tool_function_index_source_directory(char *path) { | ||||||
|   char *result = index_directory(path); |   char * result = index_directory(path); | ||||||
|   if (!result) |   if(!result) | ||||||
|     return strdup("Failed to index directory!"); |       return strdup("Failed to index directory!"); | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1214,32 +1207,33 @@ struct json_object *tool_description_linux_terminal() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char *tool_function_mkdir(char *path) { | char *tool_function_mkdir(char *path) { | ||||||
|   char temp[2048]; |     char temp[2048]; | ||||||
|   char *p = NULL; |     char *p = NULL; | ||||||
|   size_t len; |     size_t len; | ||||||
| 
 | 
 | ||||||
|   snprintf(temp, sizeof(temp), "%s", path); |     snprintf(temp, sizeof(temp), "%s", path); | ||||||
|   len = strlen(temp); |     len = strlen(temp); | ||||||
| 
 | 
 | ||||||
|   if (temp[len - 1] == '/') { |     if (temp[len - 1] == '/') { | ||||||
|     temp[len - 1] = '\0'; |         temp[len - 1] = '\0'; | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   for (p = temp + 1; *p; p++) { |  | ||||||
|     if (*p == '/') { |  | ||||||
|       *p = '\0'; |  | ||||||
|       if (mkdir(temp, 0777) != 0 && errno != EEXIST) { |  | ||||||
|         return strdup("Failed to create directory!"); |  | ||||||
|       } |  | ||||||
|       *p = '/'; |  | ||||||
|     } |     } | ||||||
|   } | 
 | ||||||
|   if (mkdir(temp, 0777) != 0 && errno != EEXIST) { |     for (p = temp + 1; *p; p++) { | ||||||
|     return strdup("Failed to create directory!"); |         if (*p == '/') { | ||||||
|   } |             *p = '\0'; | ||||||
|   return strdup("Directory successfully created."); |             if (mkdir(temp, 0777) != 0 && errno != EEXIST) { | ||||||
|  |                 return strdup("Failed to create directory!"); | ||||||
|  |             } | ||||||
|  |             *p = '/'; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if (mkdir(temp, 0777) != 0 && errno != EEXIST) { | ||||||
|  |         return strdup("Failed to create directory!"); | ||||||
|  |     } | ||||||
|  |     return strdup("Directory successfully created."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| struct json_object *tool_description_mkdir() { | struct json_object *tool_description_mkdir() { | ||||||
|   struct json_object *root = json_object_new_object(); |   struct json_object *root = json_object_new_object(); | ||||||
|   json_object_object_add(root, "type", json_object_new_string("function")); |   json_object_object_add(root, "type", json_object_new_string("function")); | ||||||
| @ -1568,18 +1562,15 @@ struct json_object *tools_execute(struct json_object *tools_array) { | |||||||
|         } |         } | ||||||
|       } else if (!strcmp(function_name, "python_execute")) { |       } else if (!strcmp(function_name, "python_execute")) { | ||||||
|         struct json_object *arguments_obj; |         struct json_object *arguments_obj; | ||||||
|         if (json_object_object_get_ex(function_obj, "arguments", |         if (json_object_object_get_ex(function_obj, "arguments", &arguments_obj)) { | ||||||
|                                       &arguments_obj)) { |             struct json_object *arguments = json_tokener_parse(json_object_get_string(arguments_obj)); | ||||||
|           struct json_object *arguments = |             struct json_object *source_obj; | ||||||
|               json_tokener_parse(json_object_get_string(arguments_obj)); |             if (json_object_object_get_ex(arguments, "source", &source_obj)) { | ||||||
|           struct json_object *source_obj; |                 char *source = (char *)json_object_get_string(source_obj); | ||||||
|           if (json_object_object_get_ex(arguments, "source", &source_obj)) { |                 char *result = tool_function_python_execute(source); | ||||||
|             char *source = (char *)json_object_get_string(source_obj); |                 json_object_object_add(tool_result, "content", json_object_new_string(result)); | ||||||
|             char *result = tool_function_python_execute(source); |                 free(result); | ||||||
|             json_object_object_add(tool_result, "content", |             } | ||||||
|                                    json_object_new_string(result)); |  | ||||||
|             free(result); |  | ||||||
|           } |  | ||||||
|         } |         } | ||||||
|       } else { |       } else { | ||||||
|         fprintf(stderr, "Unknown function: %s\n", function_name); |         fprintf(stderr, "Unknown function: %s\n", function_name); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user