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