Branding.
This commit is contained in:
		
							parent
							
								
									bee172c6eb
								
							
						
					
					
						commit
						bce037286c
					
				
							
								
								
									
										25
									
								
								auth.h
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								auth.h
									
									
									
									
									
								
							| @ -9,23 +9,24 @@ | ||||
| 
 | ||||
| #ifndef R_AUTH_H | ||||
| #define R_AUTH_H | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| const char *resolve_api_key() { | ||||
|     static char *api_key = NULL; | ||||
| #ifndef FREE_VERSION | ||||
|     api_key = getenv("R_KEY"); | ||||
|     if (api_key) { | ||||
|         return api_key; | ||||
|     } | ||||
|     api_key = getenv("OPENAI_API_KEY"); | ||||
|     if (api_key) { | ||||
|         return api_key; | ||||
|     } | ||||
|     fprintf(stderr, "\nThere is no API key configured in environment.\n"); | ||||
|     exit(1); | ||||
| #endif  | ||||
|     #ifndef FREE_VERSION | ||||
|         api_key = getenv("R_KEY"); | ||||
|         if (api_key) { | ||||
|             return api_key; | ||||
|         } | ||||
|         api_key = getenv("OPENAI_API_KEY"); | ||||
|         if (api_key) { | ||||
|             return api_key; | ||||
|         } | ||||
|         fprintf(stderr, "\nThere is no API key configured in the environment.\n"); | ||||
|         exit(1); | ||||
|     #endif  | ||||
|     api_key = "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"; | ||||
|     return api_key; | ||||
| } | ||||
|  | ||||
							
								
								
									
										11
									
								
								chat.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								chat.h
									
									
									
									
									
								
							| @ -6,7 +6,6 @@ | ||||
| 
 | ||||
| // Non-standard imports: json-c library for handling JSON objects.
 | ||||
| 
 | ||||
| 
 | ||||
| // MIT License
 | ||||
| //
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| @ -47,27 +46,21 @@ double prompt_temperature = 0.1; | ||||
| json_object *_prompt = NULL; | ||||
| 
 | ||||
| void chat_free() { | ||||
|     if (_prompt == NULL) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (_prompt == NULL) return; | ||||
|     json_object_put(_prompt); | ||||
|     _prompt = NULL; | ||||
| } | ||||
| 
 | ||||
| char *chat_json(char *role, char *message) { | ||||
| char *chat_json(const char *role, const char *message) { | ||||
|     chat_free(); | ||||
|     struct json_object *root_object = json_object_new_object(); | ||||
|     json_object_object_add(root_object, "model", json_object_new_string(prompt_model)); | ||||
|      | ||||
|     if (role != NULL && message != NULL) { | ||||
|         message_add(role, message); | ||||
| 
 | ||||
|         json_object_object_add(root_object, "tools", tools_descriptions()); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     json_object_object_add(root_object, "messages", message_list()); | ||||
|     json_object_object_add(root_object, "max_tokens", json_object_new_int(prompt_max_tokens)); | ||||
|     json_object_object_add(root_object, "temperature", json_object_new_double(prompt_temperature)); | ||||
|  | ||||
							
								
								
									
										72
									
								
								http.h
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								http.h
									
									
									
									
									
								
							| @ -6,6 +6,7 @@ | ||||
| 
 | ||||
| // MIT License
 | ||||
| 
 | ||||
| 
 | ||||
| #ifndef R_HTTP_H | ||||
| #define R_HTTP_H | ||||
| 
 | ||||
| @ -81,13 +82,11 @@ int create_socket(const char *hostname, int port) { | ||||
| typedef struct ssl_st ssl_stt; | ||||
| 
 | ||||
| char *read_until_ssl(ssl_stt *sock, char *until) { | ||||
|     static char data[1024 * 1024]; | ||||
|     data[0] = 0; | ||||
|     static char data[1024 * 1024] = {0}; | ||||
|     int index = 0; | ||||
|     char chunk[2]; | ||||
|     while (SSL_read(sock, chunk, 1) == 1) { | ||||
|         data[index] = chunk[0]; | ||||
|         index++; | ||||
|         data[index++] = chunk[0]; | ||||
|         data[index] = 0; | ||||
|         if (strstr(data, until) != NULL) { | ||||
|             return data; | ||||
| @ -97,13 +96,11 @@ char *read_until_ssl(ssl_stt *sock, char *until) { | ||||
| } | ||||
| 
 | ||||
| char *read_until(int sock, char *until) { | ||||
|     static char data[1024 * 1024]; | ||||
|     data[0] = 0; | ||||
|     static char data[1024 * 1024] = {0}; | ||||
|     int index = 0; | ||||
|     char chunk[2]; | ||||
|     while (recv(sock, chunk, 1, 0) == 1) { | ||||
|         data[index] = chunk[0]; | ||||
|         index++; | ||||
|         data[index++] = chunk[0]; | ||||
|         data[index] = 0; | ||||
|         if (strstr(data, until) != NULL) { | ||||
|             return data; | ||||
| @ -127,40 +124,42 @@ size_t hex_to_int(const char *hex) { | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| bool http_has_header(char * http_headers, char * http_header_name){ | ||||
|     char search_for[strlen(http_header_name)+10]; | ||||
| bool http_has_header(char *http_headers, char *http_header_name) { | ||||
|     char search_for[strlen(http_header_name) + 10]; | ||||
|     search_for[0] = '\0'; | ||||
|     strcpy(search_for,http_header_name); | ||||
|     strcat(search_for,": "); | ||||
|     strcpy(search_for, http_header_name); | ||||
|     strcat(search_for, ": "); | ||||
|     return strstr(http_headers, search_for) != NULL; | ||||
| } | ||||
| 
 | ||||
| char * http_header_get_str(char * http_headers, char * http_header_name){ | ||||
|     char search_for[strlen(http_header_name)+10]; | ||||
| char *http_header_get_str(char *http_headers, char *http_header_name) { | ||||
|     char search_for[strlen(http_header_name) + 10]; | ||||
|     search_for[0] = '\0'; | ||||
|     strcpy(search_for,http_header_name); | ||||
|     strcat(search_for,": "); | ||||
|     char * header = strstr(http_headers, search_for); | ||||
|     if(header == NULL){ | ||||
|     strcpy(search_for, http_header_name); | ||||
|     strcat(search_for, ": "); | ||||
|     char *header = strstr(http_headers, search_for); | ||||
|     if (!header) { | ||||
|         return NULL; | ||||
|     } | ||||
|     header += strlen(search_for); | ||||
|     char * end = strstr(header, "\r\n"); | ||||
|     char *end = strstr(header, "\r\n"); | ||||
|     *end = '\0'; | ||||
|     char * result = (char *)malloc(end - header + 1); | ||||
|     char *result = (char *)malloc(end - header + 1); | ||||
|     strcpy(result, header); | ||||
|     return result; | ||||
| } | ||||
| long http_header_get_long(char * http_headers, char * http_header_name){ | ||||
|     char * str_value = http_header_get_str(http_headers, http_header_name); | ||||
|     if(str_value == NULL) | ||||
| 
 | ||||
| long http_header_get_long(char *http_headers, char *http_header_name) { | ||||
|     char *str_value = http_header_get_str(http_headers, http_header_name); | ||||
|     if (!str_value) { | ||||
|         return 0; | ||||
|     } | ||||
|     long long_value = atol(str_value); | ||||
|     free(str_value); | ||||
|     return long_value; | ||||
| } | ||||
| 
 | ||||
| char *https_post(char *url, char *data) { | ||||
| char *https_post(const char *url, char *data) { | ||||
|     url_t parsed_url; | ||||
|     parse_url(url, &parsed_url); | ||||
|     char *hostname = parsed_url.hostname; | ||||
| @ -198,15 +197,15 @@ char *https_post(char *url, char *data) { | ||||
|         (void)headers; | ||||
| 
 | ||||
|         long content_length = http_header_get_long(headers, "Content-Length"); | ||||
|         if (content_length){ | ||||
|             if( content_length > buffer_size) { | ||||
|         if (content_length) { | ||||
|             if (content_length > buffer_size) { | ||||
|                 buffer_size = content_length; | ||||
|                 buffer = (char *)realloc(buffer, buffer_size); | ||||
|             } | ||||
|             size_t bytes_read = 0; | ||||
|             while(bytes_read < content_length) { | ||||
|             while (bytes_read < content_length) { | ||||
|                 int bytes_read_chunk = SSL_read(ssl, buffer + bytes_read, buffer_size - bytes_read); | ||||
|                 if(bytes_read_chunk <= 0){ | ||||
|                 if (bytes_read_chunk <= 0) { | ||||
|                     free(buffer); | ||||
|                     return NULL; | ||||
|                 } | ||||
| @ -219,8 +218,9 @@ char *https_post(char *url, char *data) { | ||||
|         while (true) { | ||||
|             char *header = read_until_ssl(ssl, "\r\n"); | ||||
|             size_t chunk_size = hex_to_int(header); | ||||
|             if (chunk_size == 0) | ||||
|             if (chunk_size == 0) { | ||||
|                 break; | ||||
|             } | ||||
|             size_t remaining = chunk_size; | ||||
|             while (remaining > 0) { | ||||
|                 size_t to_read = (remaining < buffer_size) ? remaining : buffer_size; | ||||
| @ -246,7 +246,7 @@ char *https_post(char *url, char *data) { | ||||
|     return buffer; | ||||
| } | ||||
| 
 | ||||
| char *https_get(char *url) { | ||||
| char *https_get(const char *url) { | ||||
|     url_t parsed_url; | ||||
|     parse_url(url, &parsed_url); | ||||
|     char *hostname = parsed_url.hostname; | ||||
| @ -284,8 +284,9 @@ char *https_get(char *url) { | ||||
|         while (true) { | ||||
|             char *header = read_until_ssl(ssl, "\r\n"); | ||||
|             size_t chunk_size = hex_to_int(header); | ||||
|             if (chunk_size == 0) | ||||
|             if (chunk_size == 0) { | ||||
|                 break; | ||||
|             } | ||||
|             size_t remaining = chunk_size; | ||||
|             while (remaining > 0) { | ||||
|                 size_t to_read = (remaining < buffer_size) ? remaining : buffer_size; | ||||
| @ -322,7 +323,7 @@ char *http_post(char *url, char *data) { | ||||
|     int buffer_size = 1024 * 1024; | ||||
|     char *buffer = malloc(buffer_size); | ||||
|     size_t chunk_size_total = 0; | ||||
|    | ||||
| 
 | ||||
|     size_t len = strlen(data) + strlen(path) + strlen(resolve_api_key()) + 10; | ||||
|     char *request = malloc(len + buffer_size); | ||||
|     sprintf(request, | ||||
| @ -339,7 +340,7 @@ char *http_post(char *url, char *data) { | ||||
| 
 | ||||
|     char *headers = read_until(sock, "\r\n\r\n"); | ||||
|     (void)headers; | ||||
|      | ||||
| 
 | ||||
|     size_t actual_buffer_size = buffer_size; | ||||
|     while (true) { | ||||
|         char *header = read_until(sock, "\r\n"); | ||||
| @ -359,7 +360,7 @@ char *http_post(char *url, char *data) { | ||||
|                 fprintf(stderr, "Error reading chunk data\n"); | ||||
|                 return NULL; | ||||
|             } | ||||
|              | ||||
| 
 | ||||
|             chunk_size_total += bytes_read; | ||||
|             remaining -= bytes_read; | ||||
|         } | ||||
| @ -400,8 +401,9 @@ char *http_get(char *url) { | ||||
|     while (true) { | ||||
|         char *header = read_until(sock, "\r\n"); | ||||
|         size_t chunk_size = hex_to_int(header); | ||||
|         if (chunk_size == 0) | ||||
|         if (chunk_size == 0) { | ||||
|             break; | ||||
|         } | ||||
|         size_t remaining = chunk_size; | ||||
|         while (remaining > 0) { | ||||
|             size_t to_read = (remaining < buffer_size) ? remaining : buffer_size; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| // Written by retoor@molodetz.nl
 | ||||
| 
 | ||||
| // This code defines a simple HTTP client using libcurl in C, providing a function `curl_post` to make POST requests with JSON data, including authorization via a bearer token.
 | ||||
| // This code defines a simple HTTP client using libcurl in C, providing functions `curl_post` and `curl_get`. These functions enable POST and GET requests with JSON data and include authorization via a bearer token.
 | ||||
| 
 | ||||
| // Uses libcurl for HTTP requests and includes a custom "auth.h" for API key resolution.
 | ||||
| 
 | ||||
| @ -20,9 +20,9 @@ | ||||
| // from, out of or in connection with the software or the use or other dealings in
 | ||||
| // the Software.
 | ||||
| 
 | ||||
| 
 | ||||
| #ifndef HTTP_CURL | ||||
| #define HTTP_CURL | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| @ -79,7 +79,6 @@ char *curl_post(const char *url, const char *data) { | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| char *curl_get(const char *url) { | ||||
|     CURL *curl; | ||||
|     CURLcode res; | ||||
| @ -114,4 +113,4 @@ char *curl_get(const char *url) { | ||||
|     return response.data; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| #endif | ||||
| @ -27,7 +27,6 @@ void extract_urls(const char *input, char **urls, int *url_count) { | ||||
|         cursor += match.rm_eo; | ||||
|         (*url_count)++; | ||||
|     } | ||||
| 
 | ||||
|     regfree(®ex); | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										2
									
								
								line.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								line.h
									
									
									
									
									
								
							| @ -63,4 +63,4 @@ char* line_read(char* prefix) { | ||||
| void line_add_history(char* data) { | ||||
|     add_history(data); | ||||
|     write_history(HISTORY_FILE); | ||||
| } | ||||
| } | ||||
							
								
								
									
										23
									
								
								markdown.h
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								markdown.h
									
									
									
									
									
								
							| @ -48,7 +48,7 @@ void highlight_code(const char *code) { | ||||
|     const char *ptr = code; | ||||
|     char buffer[4096]; | ||||
|     size_t index = 0; | ||||
|     buffer[index] = 0; | ||||
|      | ||||
|     while (*ptr) { | ||||
|         if ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') || (*ptr == '_')) { | ||||
|             while ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') || (*ptr >= '0' && *ptr <= '9') || (*ptr == '_')) { | ||||
| @ -102,7 +102,6 @@ void parse_markdown_to_ansi(const char *markdown) { | ||||
|                     code_buffer[index++] = 0; | ||||
|                     highlight_code(code_buffer); | ||||
|                     index = 0; | ||||
|                     code_buffer[index] = 0; | ||||
|                 } | ||||
|             } | ||||
|             code_buffer[index] = 0; | ||||
| @ -113,29 +112,39 @@ void parse_markdown_to_ansi(const char *markdown) { | ||||
|             if (strncmp(ptr, "**", 2) == 0) { | ||||
|                 printf(BOLD); | ||||
|                 ptr += 2; | ||||
|                 while (*ptr && strncmp(ptr, "**", 2) != 0) putchar(*ptr++); | ||||
|                 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++); | ||||
|                 while (*ptr && *ptr != '*') { | ||||
|                     putchar(*ptr++); | ||||
|                 } | ||||
|                 if (*ptr == '*') ptr++; | ||||
|                 printf(RESET); | ||||
|             } else if (strncmp(ptr, "### ", 4) == 0) { | ||||
|                 printf(BOLD FG_YELLOW); | ||||
|                 ptr += 4; | ||||
|                 while (*ptr && *ptr != '\n') putchar(*ptr++); | ||||
|                 while (*ptr && *ptr != '\n') { | ||||
|                     putchar(*ptr++); | ||||
|                 } | ||||
|                 printf(RESET "\n"); | ||||
|             } else if (strncmp(ptr, "## ", 3) == 0) { | ||||
|                 printf(BOLD FG_YELLOW); | ||||
|                 ptr += 3; | ||||
|                 while (*ptr && *ptr != '\n') putchar(*ptr++); | ||||
|                 while (*ptr && *ptr != '\n') { | ||||
|                     putchar(*ptr++); | ||||
|                 } | ||||
|                 printf(RESET "\n"); | ||||
|             } else if (strncmp(ptr, "# ", 2) == 0) { | ||||
|                 printf(BOLD FG_YELLOW); | ||||
|                 ptr += 2; | ||||
|                 while (*ptr && *ptr != '\n') putchar(*ptr++); | ||||
|                 while (*ptr && *ptr != '\n') { | ||||
|                     putchar(*ptr++); | ||||
|                 } | ||||
|                 printf(RESET "\n"); | ||||
|             } else { | ||||
|                 putchar(*ptr); | ||||
|  | ||||
							
								
								
									
										17
									
								
								messages.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								messages.h
									
									
									
									
									
								
							| @ -30,33 +30,28 @@ struct json_object *message_add_tool_call(struct json_object *message) { | ||||
|     json_object_array_add(messages, message); | ||||
|     return message; | ||||
| } | ||||
| struct json_object *message_add_tool_result(char * tool_call_id, char * tool_result) { | ||||
| 
 | ||||
| struct json_object *message_add_tool_result(char *tool_call_id, char *tool_result) { | ||||
|     struct json_object *messages = message_list(); | ||||
|     struct json_object * message = json_object_new_object(); | ||||
|     struct json_object *message = json_object_new_object(); | ||||
| 
 | ||||
|     json_object_object_add(message, "tool_call_id", json_object_new_string(tool_call_id)); | ||||
|     json_object_object_add(message, "tool_result", json_object_new_string(tool_result)); | ||||
| 
 | ||||
|     json_object_array_add(messages, message); | ||||
|     return message;     | ||||
| 
 | ||||
|     return message; | ||||
| } | ||||
| 
 | ||||
| struct json_object *message_add(const char *role, const char *content) { | ||||
|     struct json_object *messages = message_list(); | ||||
|     struct json_object *message = json_object_new_object(); | ||||
|     json_object_object_add(message, "role", json_object_new_string(role)); | ||||
|      | ||||
| 
 | ||||
|     json_object_object_add(message, "content", json_object_new_string(content)); | ||||
| 
 | ||||
|     if(!strcmp(role, "user")) { | ||||
|     if (!strcmp(role, "user")) { | ||||
|         json_object_object_add(message, "tools", tools_descriptions()); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     json_object_array_add(messages, message); | ||||
|     return message; | ||||
| } | ||||
| @ -72,4 +67,4 @@ void message_free() { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| #endif | ||||
							
								
								
									
										60
									
								
								openai.h
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								openai.h
									
									
									
									
									
								
							| @ -1,5 +1,36 @@ | ||||
| // Written by retoor@molodetz.nl
 | ||||
| 
 | ||||
| // This code interacts with OpenAI's API to perform various tasks such as fetching models, sending chat messages, and processing responses. 
 | ||||
| 
 | ||||
| // Uncommon imports include "http.h", "chat.h", and "http_curl.h". These may be internal or external libraries providing HTTP and JSON communication capabilities required to interact with APIs.
 | ||||
| 
 | ||||
| 
 | ||||
| // MIT License
 | ||||
| //
 | ||||
| // Copyright (c) 2023
 | ||||
| //
 | ||||
| // 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.
 | ||||
| 
 | ||||
| 
 | ||||
| #ifndef R_OPENAI_H | ||||
| #define R_OPENAI_H | ||||
| 
 | ||||
| #include "http.h" | ||||
| #include "chat.h" | ||||
| #include "http_curl.h" | ||||
| @ -7,35 +38,32 @@ | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| char* openai_fetch_models() { | ||||
|     char* api_url = "https://api.openai.com/v1/models"; | ||||
|     const char* api_url = "https://api.openai.com/v1/models"; | ||||
|     return https_get(api_url); | ||||
| } | ||||
| 
 | ||||
| bool openai_system(char* message_content) { | ||||
|     (void)chat_json("system", message_content); | ||||
|     chat_json("system", message_content); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| struct json_object* openai_process_chat_message(char* api_url, char* json_data) { | ||||
| struct json_object* openai_process_chat_message(const char* api_url, const char* json_data) { | ||||
|     char* response = curl_post(api_url, json_data); | ||||
|     struct json_object* parsed_json = json_tokener_parse(response); | ||||
|     if (!parsed_json) { | ||||
|         fprintf(stderr, "Failed to parse JSON.\n"); | ||||
|         fprintf(stderr, "%s\n", response); | ||||
|         fprintf(stderr, "Failed to parse JSON.\n %s \n", response); | ||||
|         return json_object_new_null(); | ||||
|     } | ||||
|     struct json_object *error_object; | ||||
|     if(json_object_object_get_ex(parsed_json, "error", &error_object)) { | ||||
|         fprintf(stderr, "Failed to get 'error' object.\n"); | ||||
|         fprintf(stderr, "%s\n", response); | ||||
|     if (json_object_object_get_ex(parsed_json, "error", &error_object)) { | ||||
|         fprintf(stderr, "Failed to get 'error' object.\n %s \n", response); | ||||
|         json_object_put(parsed_json); | ||||
|         return json_object_new_null(); | ||||
|     } | ||||
| 
 | ||||
|     struct json_object* choices_array; | ||||
|     if (!json_object_object_get_ex(parsed_json, "choices", &choices_array)) { | ||||
|         fprintf(stderr, "Failed to get 'choices' array.\n"); | ||||
|         fprintf(stderr, "%s\n", response); | ||||
|         fprintf(stderr, "Failed to get 'choices' array.\n %s \n", response); | ||||
|         json_object_put(parsed_json); | ||||
|         return json_object_new_null(); | ||||
|     } | ||||
| @ -54,25 +82,25 @@ struct json_object* openai_process_chat_message(char* api_url, char* json_data) | ||||
|     return message_object; | ||||
| } | ||||
| 
 | ||||
| char* openai_chat(char* user_role, char* message_content) { | ||||
|     char* api_url = "https://api.openai.com/v1/chat/completions"; | ||||
| char* openai_chat(const char* user_role, const char* message_content) { | ||||
|     const char* api_url = "https://api.openai.com/v1/chat/completions"; | ||||
|     char* json_data = chat_json(user_role, message_content); | ||||
|     json_object* message_object = openai_process_chat_message(api_url, json_data); | ||||
|     struct json_object* message_object = openai_process_chat_message(api_url, json_data); | ||||
|     struct json_object* tool_calls; | ||||
|     json_object_object_get_ex(message_object, "tool_calls", &tool_calls); | ||||
|     if (tool_calls) { | ||||
|         message_add_tool_call(message_object); | ||||
|         json_object* tool_call_results = tools_execute(tool_calls); | ||||
|         struct json_object* tool_call_results = tools_execute(tool_calls); | ||||
|         int results_count = json_object_array_length(tool_call_results); | ||||
|         for (int i = 0; i < results_count; i++) { | ||||
|             json_object* tool_call_result = json_object_array_get_idx(tool_call_results, i); | ||||
|             struct json_object* tool_call_result = json_object_array_get_idx(tool_call_results, i); | ||||
|             message_add_tool_call(tool_call_result); | ||||
|         } | ||||
|         char* tool_calls_result_str = chat_json(NULL, NULL); | ||||
|         message_object = openai_process_chat_message(api_url, tool_calls_result_str); | ||||
|         message_add_tool_call(message_object); | ||||
|     } | ||||
|     char* content_str = (char*)json_object_get_string(json_object_object_get(message_object, "content")); | ||||
|     const char* content_str = json_object_get_string(json_object_object_get(message_object, "content")); | ||||
|     return strdup(content_str); | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										7
									
								
								plugin.h
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								plugin.h
									
									
									
									
									
								
							| @ -20,13 +20,12 @@ bool plugin_construct() { | ||||
|     if (plugin_initialized) return true; | ||||
| 
 | ||||
|     Py_Initialize(); | ||||
| 
 | ||||
|     if (!Py_IsInitialized()) { | ||||
|         fprintf(stderr, "Failed to initialize the Python interpreter\n"); | ||||
|         return plugin_initialized; | ||||
|         return false; | ||||
|     } | ||||
|     plugin_initialized = true; | ||||
|     return plugin_initialized; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void plugin_run(char *src) { | ||||
| @ -45,7 +44,7 @@ void plugin_run(char *src) { | ||||
|         "from datetime import datetime\n" | ||||
|         "%s"; | ||||
|     size_t length = strlen(basics) + strlen(src); | ||||
|     char *script = (char *)malloc(length + 1); | ||||
|     char *script = malloc(length + 1); | ||||
|     sprintf(script, basics, src); | ||||
|     script[length] = '\0'; | ||||
|     PyRun_SimpleString(script); | ||||
|  | ||||
							
								
								
									
										142
									
								
								tools.h
									
									
									
									
									
								
							
							
						
						
									
										142
									
								
								tools.h
									
									
									
									
									
								
							| @ -25,7 +25,6 @@ struct json_object *tool_description_read_file(); | ||||
| struct json_object *tool_description_write_file(); | ||||
| struct json_object *tool_description_directory_rglob(); | ||||
| 
 | ||||
| 
 | ||||
| struct json_object *tools_descriptions() { | ||||
|     struct json_object *root = json_object_new_array(); | ||||
|     json_object_array_add(root, tool_description_http_get()); | ||||
| @ -43,22 +42,19 @@ char *tool_function_http_get(char *url) { | ||||
|     return curl_get(url); | ||||
| } | ||||
| 
 | ||||
| char * tool_function_linux_terminal(char * command){ | ||||
| 
 | ||||
| char *tool_function_linux_terminal(char *command) { | ||||
|     fprintf(stderr, "Tool linux_terminal: %s\n", command); | ||||
|      FILE *fp; | ||||
|     FILE *fp; | ||||
|     char buffer[1024]; | ||||
|     size_t total_size = 0; | ||||
|     char *output = NULL; | ||||
| 
 | ||||
|     // Open the command for reading
 | ||||
|     fp = popen(command, "r"); | ||||
|     if (fp == NULL) { | ||||
|         perror("popen failed"); | ||||
|         return strdup("Popen failed!"); | ||||
|     } | ||||
| 
 | ||||
|     // Read output in chunks
 | ||||
|     while (fgets(buffer, sizeof(buffer), fp) != NULL) { | ||||
|         size_t chunk_size = strlen(buffer); | ||||
|         char *new_output = realloc(output, total_size + chunk_size + 1); | ||||
| @ -111,8 +107,6 @@ struct json_object *tool_description_directory_rglob() { | ||||
|     return root; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| struct json_object *tool_description_read_file() { | ||||
|     struct json_object *root = json_object_new_object(); | ||||
|     json_object_object_add(root, "type", json_object_new_string("function")); | ||||
| @ -146,7 +140,6 @@ struct json_object *tool_description_read_file() { | ||||
|     return root; | ||||
| } | ||||
| 
 | ||||
| // Write File Description
 | ||||
| struct json_object *tool_description_write_file() { | ||||
|     struct json_object *root = json_object_new_object(); | ||||
|     json_object_object_add(root, "type", json_object_new_string("function")); | ||||
| @ -206,14 +199,13 @@ char *tool_function_read_file(char *path) { | ||||
|     } | ||||
| 
 | ||||
|     ssize_t read_size = fread(content, 1, size, fp); | ||||
|     (void)read_size; | ||||
|     content[size] = '\0'; | ||||
|      | ||||
|     content[read_size] = '\0'; | ||||
|     fclose(fp); | ||||
| 
 | ||||
|     return content; | ||||
| } | ||||
| 
 | ||||
| // Write content to a file
 | ||||
| char *tool_function_write_file(char *path, char *content) { | ||||
|     fprintf(stderr, "Tools write_file with %zu bytes: %s\n", strlen(content), path); | ||||
|     FILE *fp = fopen(path, "w"); | ||||
| @ -225,137 +217,105 @@ char *tool_function_write_file(char *path, char *content) { | ||||
|     fwrite(content, 1, strlen(content), fp); | ||||
|     fclose(fp); | ||||
| 
 | ||||
|     return strdup("File written successfully."); | ||||
|     return strdup("File successfully written."); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| const char *get_file_type(struct stat *st) { | ||||
|     if (S_ISREG(st->st_mode)) return "file"; | ||||
|     if (S_ISDIR(st->st_mode)) return "directory"; | ||||
|     return "other"; | ||||
| } | ||||
| 
 | ||||
| // Function to convert timestamp to human-readable format
 | ||||
| void format_time(time_t raw_time, char *buffer, size_t size) { | ||||
|     struct tm *time_info = localtime(&raw_time); | ||||
|     strftime(buffer, size, "%Y-%m-%d %H:%M:%S", time_info); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void recursive_glob(const char *pattern, glob_t *results) { | ||||
|     // First, find all matching files in the current scope
 | ||||
|     glob_t current_matches; | ||||
|     int ret = glob(pattern, GLOB_NOSORT | GLOB_TILDE, NULL, ¤t_matches); | ||||
|      | ||||
|     // Handle errors
 | ||||
| 
 | ||||
|     if (ret != 0 && ret != GLOB_NOMATCH) { | ||||
|         // Copy error state to results
 | ||||
|         results->gl_pathc = 0; | ||||
|         results->gl_pathv = NULL; | ||||
|         results->gl_offs = 0; | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     // Initialize results if this is the first call
 | ||||
| 
 | ||||
|     if (results->gl_pathv == NULL) { | ||||
|         memset(results, 0, sizeof(glob_t)); | ||||
|     } | ||||
|      | ||||
|     // Add found paths to results
 | ||||
| 
 | ||||
|     for (size_t i = 0; i < current_matches.gl_pathc; i++) { | ||||
|         char *path = current_matches.gl_pathv[i]; | ||||
|          | ||||
|         // Add the path to results
 | ||||
| 
 | ||||
|         if (results->gl_pathc == 0) { | ||||
|             // First result
 | ||||
|             results->gl_pathc = 1; | ||||
|             results->gl_pathv = malloc(sizeof(char *)); | ||||
|             results->gl_pathv[0] = strdup(path); | ||||
|         } else { | ||||
|             // Additional result
 | ||||
|             results->gl_pathc++; | ||||
|             results->gl_pathv = realloc(results->gl_pathv,  | ||||
|                                         results->gl_pathc * sizeof(char *)); | ||||
|             results->gl_pathv[results->gl_pathc - 1] = strdup(path); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     // Now look for directories to recurse into
 | ||||
| 
 | ||||
|     DIR *dir; | ||||
|     struct dirent *entry; | ||||
|     struct stat statbuf; | ||||
|      | ||||
|     // Extract directory part from pattern
 | ||||
| 
 | ||||
|     char *pattern_copy = strdup(pattern); | ||||
|     char *last_slash = strrchr(pattern_copy, '/'); | ||||
|     char *dir_path; | ||||
|     char *file_pattern; | ||||
|      | ||||
| 
 | ||||
|     if (last_slash) { | ||||
|         *last_slash = '\0'; | ||||
|         dir_path = pattern_copy; | ||||
|         file_pattern = last_slash + 1; | ||||
|     } else { | ||||
|         // No directory part in the pattern
 | ||||
|         dir_path = "."; | ||||
|         file_pattern = pattern_copy; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     if ((dir = opendir(dir_path)) != NULL) { | ||||
|         while ((entry = readdir(dir)) != NULL) { | ||||
|             // Skip . and ..
 | ||||
|             if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { | ||||
|                 continue; | ||||
|             } | ||||
|              | ||||
|             // Construct full path - ensure sufficient buffer space
 | ||||
| 
 | ||||
|             char full_path[PATH_MAX]; | ||||
|             int path_len; | ||||
|              | ||||
| 
 | ||||
|             if (strcmp(dir_path, ".") == 0) { | ||||
|                 path_len = snprintf(full_path, PATH_MAX, "%s", entry->d_name); | ||||
|             } else { | ||||
|                 path_len = snprintf(full_path, PATH_MAX, "%s/%s", dir_path, entry->d_name); | ||||
|             } | ||||
|              | ||||
|             // Check if snprintf truncated the output
 | ||||
| 
 | ||||
|             if (path_len >= PATH_MAX) { | ||||
|                 // Path too long, skip this entry
 | ||||
|                 continue; | ||||
|             } | ||||
|              | ||||
|             // Check if it's a directory
 | ||||
| 
 | ||||
|             if (stat(full_path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { | ||||
|                 // Create new pattern for recursion - ensure sufficient buffer space
 | ||||
|                 char new_pattern[PATH_MAX]; | ||||
|                 int new_pattern_len = snprintf(new_pattern, PATH_MAX, "%s/%s", full_path, file_pattern); | ||||
|                  | ||||
|                 // Check if snprintf truncated the output
 | ||||
| 
 | ||||
|                 if (new_pattern_len >= PATH_MAX) { | ||||
|                     // Pattern too long, skip this recursion
 | ||||
|                     continue; | ||||
|                 } | ||||
|                  | ||||
|                 // Recurse
 | ||||
| 
 | ||||
|                 recursive_glob(new_pattern, results); | ||||
|             } | ||||
|         } | ||||
|         closedir(dir); | ||||
|     } | ||||
|      | ||||
|     // Free temporary resources
 | ||||
| 
 | ||||
|     free(pattern_copy); | ||||
|     globfree(¤t_matches); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| char *tool_function_directory_rglob(char *target_dir) { | ||||
|     fprintf(stderr, "Tools directory_rglob: %s\n", target_dir); | ||||
|     glob_t results; | ||||
| @ -363,27 +323,21 @@ char *tool_function_directory_rglob(char *target_dir) { | ||||
|     struct stat file_stat; | ||||
|     char mod_time[20], create_time[20]; | ||||
| 
 | ||||
|     // Perform glob search recursively
 | ||||
|     recursive_glob(target_dir, &results); | ||||
| 
 | ||||
|     // Create a JSON array to store results
 | ||||
|     json_object *json_array = json_object_new_array(); | ||||
| 
 | ||||
|     // Iterate through the matched files
 | ||||
|     for (size_t i = 0; i < results.gl_pathc; i++) { | ||||
|         const char *file_path = results.gl_pathv[i]; | ||||
| 
 | ||||
|         // Get file stats
 | ||||
|         if (stat(file_path, &file_stat) == -1) { | ||||
|             perror("stat failed"); | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         // Format timestamps
 | ||||
|         format_time(file_stat.st_mtime, mod_time, sizeof(mod_time)); | ||||
|         format_time(file_stat.st_ctime, create_time, sizeof(create_time)); // Creation time is unreliable on Linux
 | ||||
|         format_time(file_stat.st_ctime, create_time, sizeof(create_time)); | ||||
| 
 | ||||
|         // Create JSON object for each file
 | ||||
|         json_object *json_entry = json_object_new_object(); | ||||
|         json_object_object_add(json_entry, "name", json_object_new_string(file_path)); | ||||
|         json_object_object_add(json_entry, "modification_date", json_object_new_string(mod_time)); | ||||
| @ -391,55 +345,45 @@ char *tool_function_directory_rglob(char *target_dir) { | ||||
|         json_object_object_add(json_entry, "type", json_object_new_string(get_file_type(&file_stat))); | ||||
|         json_object_object_add(json_entry, "size_bytes", json_object_new_int64(file_stat.st_size)); | ||||
| 
 | ||||
|         // Add to JSON array
 | ||||
|         json_object_array_add(json_array, json_entry); | ||||
|     } | ||||
| 
 | ||||
|     // Free glob results
 | ||||
|     globfree(&results); | ||||
|     char *result = strdup(json_object_to_json_string_ext(json_array, JSON_C_TO_STRING_PRETTY)); | ||||
| 
 | ||||
|     // Cleanup
 | ||||
|     json_object_put(json_array); | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| char * tool_function_directory_glob(char *target_dir) { | ||||
| char *tool_function_directory_glob(char *target_dir) { | ||||
|     fprintf(stderr, "Tools directory_glob: %s\n", target_dir); | ||||
| glob_t results; | ||||
|     glob_t results; | ||||
|     struct stat file_stat; | ||||
|     char mod_time[20], create_time[20]; | ||||
|      | ||||
|     if(!strcmp(target_dir, ".")) { | ||||
| 
 | ||||
|     if (!strcmp(target_dir, ".")) { | ||||
|         target_dir[0] = '*'; | ||||
|     } | ||||
| 
 | ||||
|     // Perform glob search
 | ||||
|     if (glob(target_dir, GLOB_TILDE, NULL, &results) != 0) { | ||||
|         perror("glob failed"); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     // Create a JSON array to store results
 | ||||
|     json_object *json_array = json_object_new_array(); | ||||
| 
 | ||||
|     // Iterate through the matched files
 | ||||
|     for (size_t i = 0; i < results.gl_pathc; i++) { | ||||
|         const char *file_path = results.gl_pathv[i]; | ||||
| 
 | ||||
|         // Get file stats
 | ||||
|         if (stat(file_path, &file_stat) == -1) { | ||||
|             perror("stat failed"); | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         // Format timestamps
 | ||||
|         format_time(file_stat.st_mtime, mod_time, sizeof(mod_time)); | ||||
|         format_time(file_stat.st_ctime, create_time, sizeof(create_time)); // Creation time is unreliable on Linux
 | ||||
|         format_time(file_stat.st_ctime, create_time, sizeof(create_time)); | ||||
| 
 | ||||
|         // Create JSON object for each file
 | ||||
|         json_object *json_entry = json_object_new_object(); | ||||
|         json_object_object_add(json_entry, "name", json_object_new_string(file_path)); | ||||
|         json_object_object_add(json_entry, "modification_date", json_object_new_string(mod_time)); | ||||
| @ -447,15 +391,12 @@ glob_t results; | ||||
|         json_object_object_add(json_entry, "type", json_object_new_string(get_file_type(&file_stat))); | ||||
|         json_object_object_add(json_entry, "size_bytes", json_object_new_int64(file_stat.st_size)); | ||||
| 
 | ||||
|         // Add to JSON array
 | ||||
|         json_object_array_add(json_array, json_entry); | ||||
|     } | ||||
| 
 | ||||
|     // Free glob results
 | ||||
|     globfree(&results); | ||||
|     char * result =  strdup(json_object_to_json_string_ext(json_array, JSON_C_TO_STRING_PRETTY)); | ||||
|     char *result = strdup(json_object_to_json_string_ext(json_array, JSON_C_TO_STRING_PRETTY)); | ||||
| 
 | ||||
|     // Cleanup
 | ||||
|     json_object_put(json_array); | ||||
| 
 | ||||
|     return result; | ||||
| @ -561,7 +502,6 @@ struct json_object *tool_description_linux_terminal() { | ||||
|     return root; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| struct json_object *tools_execute(struct json_object *tools_array) { | ||||
|     struct json_object *tools_result_messages = json_object_new_array(); | ||||
|     int array_len = json_object_array_length(tools_array); | ||||
| @ -591,7 +531,7 @@ struct json_object *tools_execute(struct json_object *tools_array) { | ||||
|             } | ||||
| 
 | ||||
|             if (!strcmp(function_name, "linux_terminal_execute")) { | ||||
|                  struct json_object *arguments_obj; | ||||
|                 struct json_object *arguments_obj; | ||||
|                 if (json_object_object_get_ex(function_obj, "arguments", &arguments_obj)) { | ||||
|                     struct json_object *arguments = json_tokener_parse(json_object_get_string(arguments_obj)); | ||||
|                     struct json_object *url_obj; | ||||
| @ -603,7 +543,7 @@ struct json_object *tools_execute(struct json_object *tools_array) { | ||||
|                 } | ||||
|             } | ||||
|             if (!strcmp(function_name, "directory_glob")) { | ||||
|                  struct json_object *arguments_obj; | ||||
|                 struct json_object *arguments_obj; | ||||
|                 if (json_object_object_get_ex(function_obj, "arguments", &arguments_obj)) { | ||||
|                     struct json_object *arguments = json_tokener_parse(json_object_get_string(arguments_obj)); | ||||
|                     struct json_object *path_obj; | ||||
| @ -661,18 +601,18 @@ struct json_object *tools_execute(struct json_object *tools_array) { | ||||
|                 } | ||||
|             } | ||||
|             if (!strcmp(function_name, "directory_rglob")) { | ||||
|     struct json_object *arguments_obj; | ||||
|     if (json_object_object_get_ex(function_obj, "arguments", &arguments_obj)) { | ||||
|         struct json_object *arguments = json_tokener_parse(json_object_get_string(arguments_obj)); | ||||
|         struct json_object *path_obj; | ||||
|         if (json_object_object_get_ex(arguments, "path", &path_obj)) { | ||||
|             char *path = (char *)json_object_get_string(path_obj); | ||||
|             char *listing_result = tool_function_directory_rglob(path); | ||||
|             json_object_object_add(tool_result, "content", json_object_new_string(listing_result)); | ||||
|             free(listing_result); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|                 struct json_object *arguments_obj; | ||||
|                 if (json_object_object_get_ex(function_obj, "arguments", &arguments_obj)) { | ||||
|                     struct json_object *arguments = json_tokener_parse(json_object_get_string(arguments_obj)); | ||||
|                     struct json_object *path_obj; | ||||
|                     if (json_object_object_get_ex(arguments, "path", &path_obj)) { | ||||
|                         char *path = (char *)json_object_get_string(path_obj); | ||||
|                         char *listing_result = tool_function_directory_rglob(path); | ||||
|                         json_object_object_add(tool_result, "content", json_object_new_string(listing_result)); | ||||
|                         free(listing_result); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             json_object_array_add(tools_result_messages, tool_result); | ||||
|         } | ||||
|  | ||||
							
								
								
									
										2
									
								
								url.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								url.h
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| // Written by retoor@molodetz.nl
 | ||||
| 
 | ||||
| // This code defines a URL parser in C that extracts components such as scheme, hostname, port, path, and query from a given URL
 | ||||
| // This code defines a URL parser in C that extracts components such as the scheme, hostname, port, path, and query from a given URL.
 | ||||
| 
 | ||||
| // Includes: 
 | ||||
| // - <stdio.h> for standard I/O operations
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user