Update.
This commit is contained in:
parent
f6d5030812
commit
d740eb62a1
0
.gitignore
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
0
Dockerfile
Normal file → Executable file
0
Dockerfile
Normal file → Executable 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
Normal file → Executable file
0
compose.yml
Normal file → Executable file
0
database.db
Normal file → Executable file
0
database.db
Normal file → Executable file
0
db_utils.c
Normal file → Executable file
0
db_utils.c
Normal file → Executable file
0
db_utils.h
Normal file → Executable file
0
db_utils.h
Normal file → Executable file
@ -68,7 +68,8 @@ 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", resolve_api_key());
|
snprintf(bearer_header, sizeof(bearer_header), "Authorization: Bearer %s",
|
||||||
|
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);
|
||||||
@ -102,7 +103,8 @@ 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", resolve_api_key());
|
snprintf(bearer_header, sizeof(bearer_header), "Authorization: Bearer %s",
|
||||||
|
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);
|
||||||
|
424
main.c
424
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 <unistd.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.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,259 +29,263 @@ 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;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t bytes_read;
|
// Null-terminate the output
|
||||||
while ((bytes_read = fread(output + total_size, 1, buffer_size - total_size, fp)) > 0) {
|
output[total_size] = '\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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Null-terminate the output
|
pclose(fp);
|
||||||
output[total_size] = '\0';
|
return output;
|
||||||
|
|
||||||
|
|
||||||
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;
|
bool get_from_std_in = false;
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
if (strcmp(argv[i], "--stdin") == 0) {
|
if (strcmp(argv[i], "--stdin") == 0) {
|
||||||
fprintf(stderr, "Reading from stdin.\n");
|
fprintf(stderr, "Reading from stdin.\n");
|
||||||
get_from_std_in = true;
|
get_from_std_in = true;
|
||||||
} else if (strcmp(argv[i], "--verbose") == 0) {
|
} else if (strcmp(argv[i], "--verbose") == 0) {
|
||||||
is_verbose = true;
|
is_verbose = true;
|
||||||
} else if (strcmp(argv[i], "--py") == 0 && i + 1 < argc) {
|
} else if (strcmp(argv[i], "--py") == 0 && i + 1 < argc) {
|
||||||
char *py_file_path = expand_home_directory(argv[++i]);
|
char *py_file_path = expand_home_directory(argv[++i]);
|
||||||
fprintf(stderr, "Including \"%s\".\n", py_file_path);
|
fprintf(stderr, "Including \"%s\".\n", py_file_path);
|
||||||
openai_include(py_file_path);
|
openai_include(py_file_path);
|
||||||
free(py_file_path);
|
free(py_file_path);
|
||||||
} else if (strcmp(argv[i], "--free") == 0) {
|
} else if (strcmp(argv[i], "--free") == 0) {
|
||||||
auth_free();
|
auth_free();
|
||||||
} else if (strcmp(argv[i], "--context") == 0 && i + 1 < argc) {
|
} else if (strcmp(argv[i], "--context") == 0 && i + 1 < argc) {
|
||||||
char *context_file_path = argv[++i];
|
char *context_file_path = argv[++i];
|
||||||
fprintf(stderr, "Including \"%s\".\n", context_file_path);
|
fprintf(stderr, "Including \"%s\".\n", context_file_path);
|
||||||
openai_include(context_file_path);
|
openai_include(context_file_path);
|
||||||
} else if (strcmp(argv[i], "--api") == 0) {
|
} else if (strcmp(argv[i], "--api") == 0) {
|
||||||
API_MODE = true;
|
API_MODE = true;
|
||||||
} else if (strcmp(argv[i], "--nh") == 0) {
|
} else if (strcmp(argv[i], "--nh") == 0) {
|
||||||
SYNTAX_HIGHLIGHT_ENABLED = false;
|
SYNTAX_HIGHLIGHT_ENABLED = false;
|
||||||
fprintf(stderr, "Syntax highlighting disabled.\n");
|
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 {
|
} else {
|
||||||
free(prompt);
|
strcat(system, argv[i]);
|
||||||
prompt = system;
|
strcat(system, (i < argc - 1) ? " " : ".");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!*prompt) {
|
if (get_from_std_in) {
|
||||||
free(prompt);
|
if (*system)
|
||||||
return NULL;
|
openai_system(system);
|
||||||
}
|
prompt = get_prompt_from_stdin(prompt);
|
||||||
return 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;
|
|
||||||
}
|
}
|
||||||
return false;
|
render(response);
|
||||||
|
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)) {
|
|
||||||
is_verbose = !is_verbose;
|
|
||||||
fprintf(stderr, "%s\n", is_verbose ? "Verbose mode enabled" : "Verbose mode disabled");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (line && *line != '\n')
|
|
||||||
line_add_history(line);
|
|
||||||
if (!strncmp(line, "!tools", 6)) {
|
|
||||||
printf("Available tools: %s\n", json_object_to_json_string(tools_descriptions()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(line, "!models", 7)) {
|
|
||||||
printf("Current model: %s\n", openai_fetch_models());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(line, "!model", 6)) {
|
|
||||||
if (line[6] == ' ') {
|
|
||||||
set_prompt_model(line + 7);
|
|
||||||
}
|
|
||||||
printf("Current model: %s\n", get_prompt_model());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!strncmp(line, "exit", 4))
|
|
||||||
exit(0);
|
|
||||||
|
|
||||||
while (line && *line != '\n') {
|
|
||||||
char *response = openai_chat("user", line);
|
|
||||||
if (response) {
|
|
||||||
render(response);
|
|
||||||
printf("\n");
|
|
||||||
if (strstr(response, "_STEP_")) {
|
|
||||||
line = "continue";
|
|
||||||
} else {
|
|
||||||
line = NULL;
|
|
||||||
}
|
|
||||||
free(response);
|
|
||||||
} else {
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!strncmp(line, "!verbose", 8)) {
|
||||||
|
is_verbose = !is_verbose;
|
||||||
|
fprintf(stderr, "%s\n",
|
||||||
|
is_verbose ? "Verbose mode enabled" : "Verbose mode disabled");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line && *line != '\n')
|
||||||
|
line_add_history(line);
|
||||||
|
if (!strncmp(line, "!tools", 6)) {
|
||||||
|
printf("Available tools: %s\n",
|
||||||
|
json_object_to_json_string(tools_descriptions()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strncmp(line, "!models", 7)) {
|
||||||
|
printf("Current model: %s\n", openai_fetch_models());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strncmp(line, "!model", 6)) {
|
||||||
|
if (line[6] == ' ') {
|
||||||
|
set_prompt_model(line + 7);
|
||||||
|
}
|
||||||
|
printf("Current model: %s\n", get_prompt_model());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strncmp(line, "exit", 4))
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
while (line && *line != '\n') {
|
||||||
|
char *response = openai_chat("user", line);
|
||||||
|
if (response) {
|
||||||
|
render(response);
|
||||||
|
printf("\n");
|
||||||
|
if (strstr(response, "_STEP_")) {
|
||||||
|
line = "continue";
|
||||||
|
} else {
|
||||||
|
line = NULL;
|
||||||
|
}
|
||||||
|
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(payload, sizeof(payload),
|
snprintf(
|
||||||
"# LOCAL DATABASE"
|
payload, sizeof(payload),
|
||||||
"Your have a local database that you can mutate using the query tool and "
|
"# LOCAL DATABASE"
|
||||||
"the get and set tool."
|
"Your have a local database that you can mutate using the query tool and "
|
||||||
"If you set a value using the tool, make sure that the key is stemmed and lowercased to prevent double entries."
|
"the get and set tool."
|
||||||
"Dialect is sqlite. This is the schema in json format: %s. ",
|
"If you set a value using the tool, make sure that the key is stemmed "
|
||||||
schema);
|
"and lowercased to prevent double entries."
|
||||||
free(schema);
|
"Dialect is sqlite. This is the schema in json format: %s. ",
|
||||||
fprintf(stderr, "Loading... 📨");
|
schema);
|
||||||
openai_system(payload);
|
free(schema);
|
||||||
char * env_system_message = get_env_system_message();
|
fprintf(stderr, "Loading... 📨");
|
||||||
if(env_system_message && *env_system_message){
|
openai_system(payload);
|
||||||
openai_system(env_system_message);
|
char *env_system_message = get_env_system_message();
|
||||||
free(env_system_message);
|
if (env_system_message && *env_system_message) {
|
||||||
}
|
openai_system(env_system_message);
|
||||||
if (!openai_include(".rcontext.txt")) {
|
free(env_system_message);
|
||||||
openai_include("~/.rcontext.txt");
|
}
|
||||||
}
|
if (!openai_include(".rcontext.txt")) {
|
||||||
fprintf(stderr, "\r \r");
|
openai_include("~/.rcontext.txt");
|
||||||
|
}
|
||||||
|
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 {
|
||||||
if (difftime(current_time, first_sigint_time) <= 1) {
|
sigint_count = 1;
|
||||||
exit(0);
|
first_sigint_time = current_time;
|
||||||
} 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;
|
||||||
}
|
}
|
||||||
|
356
markdown.h
356
markdown.h
@ -1,45 +1,30 @@
|
|||||||
// Written by retoor@molodetz.nl
|
#include <ctype.h>
|
||||||
|
|
||||||
// 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
|
||||||
@ -75,33 +60,38 @@ 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) {
|
||||||
if ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') ||
|
// Highlight keywords
|
||||||
(*ptr == '_')) {
|
if (isalpha((unsigned char)*ptr) || *ptr == '_') {
|
||||||
while ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') ||
|
while (isalnum((unsigned char)*ptr) || *ptr == '_') {
|
||||||
(*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, buffer);
|
printf(FG_BLUE "%s" RESET FG_YELLOW, buffer);
|
||||||
} else {
|
} else {
|
||||||
printf("%s", buffer);
|
printf("%s", buffer);
|
||||||
}
|
}
|
||||||
index = 0;
|
index = 0;
|
||||||
} else if (*ptr >= '0' && *ptr <= '9') {
|
// Highlight numbers
|
||||||
while (*ptr >= '0' && *ptr <= '9') {
|
} else if (isdigit((unsigned char)*ptr)) {
|
||||||
|
while (isdigit((unsigned char)*ptr)) {
|
||||||
buffer[index++] = *ptr++;
|
buffer[index++] = *ptr++;
|
||||||
}
|
}
|
||||||
buffer[index] = 0;
|
buffer[index] = '\0';
|
||||||
printf(FG_CYAN "%s" RESET, buffer);
|
printf(FG_CYAN "%s" RESET FG_YELLOW, buffer);
|
||||||
index = 0;
|
index = 0;
|
||||||
|
// Print other characters as-is
|
||||||
} else {
|
} else {
|
||||||
putchar(*ptr);
|
putchar(*ptr);
|
||||||
ptr++;
|
ptr++;
|
||||||
@ -109,93 +99,253 @@ 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 inside_code = false;
|
bool is_start_of_line = true;
|
||||||
|
|
||||||
while (*ptr) {
|
while (*ptr) {
|
||||||
if (*ptr == '`' && *(ptr + 1) != '`') {
|
// --- Code Blocks (```) ---
|
||||||
inside_code = !inside_code;
|
if (is_start_of_line && strncmp(ptr, "```", 3) == 0) {
|
||||||
if (inside_code) {
|
ptr += 3;
|
||||||
|
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);
|
||||||
} else {
|
highlight_code(block_buffer);
|
||||||
printf(RESET);
|
printf(RESET);
|
||||||
}
|
|
||||||
ptr++;
|
ptr = code_end + 3;
|
||||||
continue;
|
if (*ptr == '\n')
|
||||||
} else if (!strncmp(ptr, "```", 3)) {
|
ptr++;
|
||||||
inside_code = !inside_code;
|
is_start_of_line = true;
|
||||||
if (inside_code) {
|
continue;
|
||||||
ptr = strstr(ptr, "\n") + 1;
|
|
||||||
} else {
|
} else {
|
||||||
ptr += 3;
|
printf(FG_YELLOW);
|
||||||
}
|
highlight_code(code_start);
|
||||||
if (*ptr == '\0') {
|
printf(RESET);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inside_code) {
|
// --- Block-level Elements (checked at the start of a line) ---
|
||||||
char code_buffer[1024 * 1024] = {0};
|
if (is_start_of_line) {
|
||||||
;
|
const char *line_start_ptr = ptr;
|
||||||
size_t index = 0;
|
int indent_level = 0;
|
||||||
|
while (*ptr == ' ') {
|
||||||
while (*ptr && *ptr != '`') {
|
indent_level++;
|
||||||
code_buffer[index++] = *ptr++;
|
|
||||||
if (*ptr == '\n' || *ptr == ' ' || *ptr == '\t' || *ptr == '.') {
|
|
||||||
code_buffer[index++] = 0;
|
|
||||||
highlight_code(code_buffer);
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code_buffer[index] = 0;
|
|
||||||
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++;
|
ptr++;
|
||||||
while (*ptr && *ptr != '*') {
|
}
|
||||||
putchar(*ptr++);
|
|
||||||
}
|
bool block_processed = true;
|
||||||
if (*ptr == '*')
|
if (strncmp(ptr, "###### ", 7) == 0) {
|
||||||
ptr++;
|
printf(BOLD FG_YELLOW);
|
||||||
printf(RESET);
|
ptr += 7;
|
||||||
|
} else if (strncmp(ptr, "##### ", 6) == 0) {
|
||||||
|
printf(BOLD FG_YELLOW);
|
||||||
|
ptr += 6;
|
||||||
|
} else if (strncmp(ptr, "#### ", 5) == 0) {
|
||||||
|
printf(BOLD FG_YELLOW);
|
||||||
|
ptr += 5;
|
||||||
} 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;
|
||||||
while (*ptr && *ptr != '\n') {
|
} else if ((strncmp(ptr, "---", 3) == 0 || strncmp(ptr, "***", 3) == 0) &&
|
||||||
putchar(*ptr++);
|
(*(ptr + 3) == '\n' || *(ptr + 3) == '\0')) {
|
||||||
}
|
printf(FG_CYAN "───────────────────────────────────────────────────────"
|
||||||
printf(RESET "\n");
|
"──────────" 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 {
|
} else {
|
||||||
putchar(*ptr);
|
const char *temp_ptr = 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++);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 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
Normal file → Executable file
0
messages.h
Normal file → Executable file
43
r.h
43
r.h
@ -32,31 +32,30 @@ 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() {
|
||||||
bool use_tools(){
|
if (getenv("R_USE_TOOLS") != NULL) {
|
||||||
if(getenv("R_USE_TOOLS") != NULL){
|
const char *value = getenv("R_USE_TOOLS");
|
||||||
const char *value = getenv("R_USE_TOOLS");
|
if (!strcmp(value, "true")) {
|
||||||
if (!strcmp(value, "true")) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!strcmp(value, "false")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!strcmp(value, "1")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!strcmp(value, "0")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
if (!strcmp(value, "false")) {
|
||||||
|
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
Normal file → Executable file
0
r.png
Normal file → Executable file
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
0
screenshot1.png
Normal file → Executable file
0
screenshot1.png
Normal file → Executable file
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
205
tools.h
205
tools.h
@ -56,7 +56,6 @@ 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() {
|
||||||
@ -66,7 +65,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());
|
||||||
@ -424,81 +423,88 @@ 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");
|
FILE *fp = fdopen(fd, "w");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return strdup("Failed to open temporary file for writing.");
|
return strdup("Failed to open temporary file for writing.");
|
||||||
}
|
}
|
||||||
fwrite(source_code, 1, strlen(source_code), fp);
|
fwrite(source_code, 1, strlen(source_code), fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
char command[4096];
|
char command[4096];
|
||||||
snprintf(command, sizeof(command), "python3 '%s' 2>&1", tmp_file);
|
snprintf(command, sizeof(command), "python3 '%s' 2>&1", tmp_file);
|
||||||
|
|
||||||
FILE *proc = popen(command, "r");
|
FILE *proc = popen(command, "r");
|
||||||
if (!proc) {
|
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);
|
unlink(tmp_file);
|
||||||
return output;
|
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_new_string("python_execute"));
|
json_object_object_add(function, "name",
|
||||||
json_object_object_add(function, "description", json_object_new_string("Executes Python source code using the python3 interpreter and returns stdout/stderr."));
|
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."));
|
||||||
|
|
||||||
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(source, "description", json_object_new_string("Python source code to execute."));
|
json_object_object_add(
|
||||||
json_object_object_add(properties, "source", source);
|
source, "description",
|
||||||
|
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_new_boolean(0));
|
json_object_object_add(parameters, "additionalProperties",
|
||||||
json_object_object_add(function, "parameters", parameters);
|
json_object_new_boolean(0));
|
||||||
|
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 ----
|
||||||
|
|
||||||
@ -646,9 +652,10 @@ 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(path, "description",
|
json_object_object_add(
|
||||||
json_object_new_string(
|
path, "description",
|
||||||
"Executable with parameters to execute interactively."));
|
json_object_new_string(
|
||||||
|
"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);
|
||||||
@ -816,9 +823,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1207,33 +1214,32 @@ 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++) {
|
for (p = temp + 1; *p; p++) {
|
||||||
if (*p == '/') {
|
if (*p == '/') {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
if (mkdir(temp, 0777) != 0 && errno != EEXIST) {
|
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("Failed to create directory!");
|
||||||
|
}
|
||||||
|
*p = '/';
|
||||||
}
|
}
|
||||||
return strdup("Directory successfully created.");
|
}
|
||||||
|
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"));
|
||||||
@ -1562,15 +1568,18 @@ 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", &arguments_obj)) {
|
if (json_object_object_get_ex(function_obj, "arguments",
|
||||||
struct json_object *arguments = json_tokener_parse(json_object_get_string(arguments_obj));
|
&arguments_obj)) {
|
||||||
struct json_object *source_obj;
|
struct json_object *arguments =
|
||||||
if (json_object_object_get_ex(arguments, "source", &source_obj)) {
|
json_tokener_parse(json_object_get_string(arguments_obj));
|
||||||
char *source = (char *)json_object_get_string(source_obj);
|
struct json_object *source_obj;
|
||||||
char *result = tool_function_python_execute(source);
|
if (json_object_object_get_ex(arguments, "source", &source_obj)) {
|
||||||
json_object_object_add(tool_result, "content", json_object_new_string(result));
|
char *source = (char *)json_object_get_string(source_obj);
|
||||||
free(result);
|
char *result = tool_function_python_execute(source);
|
||||||
}
|
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