// retoor #include "tool.h" #include "r_config.h" #include #include #include #include #include #include #include #include #include #include static char *expand_home_directory(const char *path); static const char *get_file_type(struct stat *st); static void format_time(time_t raw_time, char *buffer, size_t size); static struct json_object *read_file_get_description(void); static char *read_file_execute(tool_t *self, struct json_object *args); static void read_file_print_action(const char *name, struct json_object *args); static struct json_object *write_file_get_description(void); static char *write_file_execute(tool_t *self, struct json_object *args); static void write_file_print_action(const char *name, struct json_object *args); static struct json_object *directory_glob_get_description(void); static char *directory_glob_execute(tool_t *self, struct json_object *args); static void directory_glob_print_action(const char *name, struct json_object *args); static struct json_object *mkdir_get_description(void); static char *mkdir_execute(tool_t *self, struct json_object *args); static void mkdir_print_action(const char *name, struct json_object *args); static struct json_object *chdir_get_description(void); static char *chdir_execute(tool_t *self, struct json_object *args); static void chdir_print_action(const char *name, struct json_object *args); static struct json_object *getpwd_get_description(void); static char *getpwd_execute(tool_t *self, struct json_object *args); static void getpwd_print_action(const char *name, struct json_object *args); static const tool_vtable_t read_file_vtable = { .get_description = read_file_get_description, .execute = read_file_execute, .print_action = read_file_print_action }; static const tool_vtable_t write_file_vtable = { .get_description = write_file_get_description, .execute = write_file_execute, .print_action = write_file_print_action }; static const tool_vtable_t directory_glob_vtable = { .get_description = directory_glob_get_description, .execute = directory_glob_execute, .print_action = directory_glob_print_action }; static const tool_vtable_t mkdir_vtable = { .get_description = mkdir_get_description, .execute = mkdir_execute, .print_action = mkdir_print_action }; static const tool_vtable_t chdir_vtable = { .get_description = chdir_get_description, .execute = chdir_execute, .print_action = chdir_print_action }; static const tool_vtable_t getpwd_vtable = { .get_description = getpwd_get_description, .execute = getpwd_execute, .print_action = getpwd_print_action }; static tool_t read_file_tool = { .vtable = &read_file_vtable, .name = "read_file" }; static tool_t write_file_tool = { .vtable = &write_file_vtable, .name = "write_file" }; static tool_t directory_glob_tool = { .vtable = &directory_glob_vtable, .name = "directory_glob" }; static tool_t mkdir_tool = { .vtable = &mkdir_vtable, .name = "mkdir" }; static tool_t chdir_tool = { .vtable = &chdir_vtable, .name = "chdir" }; static tool_t getpwd_tool = { .vtable = &getpwd_vtable, .name = "getpwd" }; tool_t *tool_read_file_create(void) { return &read_file_tool; } tool_t *tool_write_file_create(void) { return &write_file_tool; } tool_t *tool_directory_glob_create(void) { return &directory_glob_tool; } tool_t *tool_mkdir_create(void) { return &mkdir_tool; } tool_t *tool_chdir_create(void) { return &chdir_tool; } tool_t *tool_getpwd_create(void) { return &getpwd_tool; } static char *expand_home_directory(const char *path) { if (!path) return NULL; if (path[0] != '~') return strdup(path); const char *home_dir = getenv("HOME"); if (!home_dir) home_dir = getenv("USERPROFILE"); if (!home_dir) return strdup(path); size_t home_len = strlen(home_dir); size_t path_len = strlen(path); char *expanded = malloc(home_len + path_len); if (!expanded) return NULL; strcpy(expanded, home_dir); strcat(expanded, path + 1); return expanded; } static 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"; } static 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); } static char *make_dir_recursive(const char *path) { char temp[4096]; char *p = NULL; size_t len = strlen(path); if (len >= sizeof(temp)) return strdup("Path too long!"); memcpy(temp, path, len + 1); if (temp[len - 1] == '/') temp[len - 1] = '\0'; for (p = temp + 1; *p; p++) { if (*p == '/') { *p = '\0'; if (mkdir(temp, 0777) != 0 && errno != EEXIST) { return strdup("Failed to create directory!"); } *p = '/'; } } if (mkdir(temp, 0777) != 0 && errno != EEXIST) { return strdup("Failed to create directory!"); } return strdup("Directory successfully created."); } static void ensure_parent_directory_exists(const char *path_including_file_name) { if (!path_including_file_name) return; char *path = strdup(path_including_file_name); if (!path) return; char *last_slash = strrchr(path, '/'); if (last_slash) { *last_slash = '\0'; char *result = make_dir_recursive(path); free(result); } free(path); } static void read_file_print_action(const char *name, struct json_object *args) { (void)name; if (!args) return; struct json_object *path; if (json_object_object_get_ex(args, "path", &path)) { fprintf(stderr, " -> Reading file: %s\n", json_object_get_string(path)); } } static char *read_file_execute(tool_t *self, struct json_object *args) { (void)self; struct json_object *path_obj; if (!json_object_object_get_ex(args, "path", &path_obj)) { return strdup("Error: missing 'path' argument"); } char *expanded_path = expand_home_directory(json_object_get_string(path_obj)); if (!expanded_path) return strdup("Failed to expand path!"); FILE *fp = fopen(expanded_path, "r"); free(expanded_path); if (!fp) return strdup("Failed to open file for reading!"); fseek(fp, 0, SEEK_END); long size = ftell(fp); if (size < 0) { fclose(fp); return strdup("Failed to determine file size!"); } rewind(fp); char *content = malloc((size_t)size + 1); if (!content) { fclose(fp); return strdup("Memory allocation failed!"); } size_t read_size = fread(content, 1, (size_t)size, fp); content[read_size] = '\0'; fclose(fp); return content; } static struct json_object *read_file_get_description(void) { struct json_object *root = json_object_new_object(); json_object_object_add(root, "type", json_object_new_string("function")); struct json_object *function = json_object_new_object(); json_object_object_add(function, "name", json_object_new_string("read_file")); json_object_object_add(function, "description", json_object_new_string("Reads / opens / loads a file and returns its contents as a string.")); struct json_object *parameters = json_object_new_object(); json_object_object_add(parameters, "type", json_object_new_string("object")); struct json_object *properties = 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, "description", json_object_new_string("Path to the file to read / open / load.")); json_object_object_add(properties, "path", path); json_object_object_add(parameters, "properties", properties); struct json_object *required = json_object_new_array(); json_object_array_add(required, json_object_new_string("path")); json_object_object_add(parameters, "required", required); json_object_object_add(parameters, "additionalProperties", json_object_new_boolean(0)); json_object_object_add(function, "parameters", parameters); r_config_handle cfg = r_config_get_instance(); if (r_config_use_strict(cfg)) { json_object_object_add(function, "strict", json_object_new_boolean(1)); } json_object_object_add(root, "function", function); return root; } static void write_file_print_action(const char *name, struct json_object *args) { (void)name; if (!args) return; struct json_object *path; if (json_object_object_get_ex(args, "path", &path)) { fprintf(stderr, " -> Writing file: %s\n", json_object_get_string(path)); } } static char *write_file_execute(tool_t *self, struct json_object *args) { (void)self; struct json_object *path_obj, *content_obj; if (!json_object_object_get_ex(args, "path", &path_obj)) { return strdup("Error: missing 'path' argument"); } if (!json_object_object_get_ex(args, "content", &content_obj)) { return strdup("Error: missing 'content' argument"); } const char *path = json_object_get_string(path_obj); const char *content = json_object_get_string(content_obj); ensure_parent_directory_exists(path); FILE *fp = fopen(path, "w+"); if (!fp) return strdup("Failed to open file for writing!"); fwrite(content, 1, strlen(content), fp); fclose(fp); return strdup("File successfully written."); } static struct json_object *write_file_get_description(void) { struct json_object *root = json_object_new_object(); json_object_object_add(root, "type", json_object_new_string("function")); struct json_object *function = json_object_new_object(); json_object_object_add(function, "name", json_object_new_string("write_file")); json_object_object_add(function, "description", json_object_new_string("Writes / saves / stores content to a file. Content should be in plain format, not json encoded.")); struct json_object *parameters = json_object_new_object(); json_object_object_add(parameters, "type", json_object_new_string("object")); struct json_object *properties = 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, "description", json_object_new_string("Path to the plain file to write / save / store.")); json_object_object_add(properties, "path", path); struct json_object *content = json_object_new_object(); json_object_object_add(content, "type", json_object_new_string("string")); json_object_object_add(content, "description", json_object_new_string("Plain content to write / save / store into the file.")); json_object_object_add(properties, "content", content); json_object_object_add(parameters, "properties", properties); struct json_object *required = json_object_new_array(); json_object_array_add(required, json_object_new_string("path")); json_object_array_add(required, json_object_new_string("content")); json_object_object_add(parameters, "required", required); json_object_object_add(parameters, "additionalProperties", json_object_new_boolean(0)); json_object_object_add(function, "parameters", parameters); r_config_handle cfg = r_config_get_instance(); if (r_config_use_strict(cfg)) { json_object_object_add(function, "strict", json_object_new_boolean(1)); } json_object_object_add(root, "function", function); return root; } static void directory_glob_print_action(const char *name, struct json_object *args) { (void)name; if (!args) return; struct json_object *path; if (json_object_object_get_ex(args, "path", &path)) { fprintf(stderr, " -> Listing: %s\n", json_object_get_string(path)); } } static char *directory_glob_execute(tool_t *self, struct json_object *args) { (void)self; struct json_object *path_obj; if (!json_object_object_get_ex(args, "path", &path_obj)) { return strdup("Error: missing 'path' argument"); } char target_dir[PATH_MAX]; strncpy(target_dir, json_object_get_string(path_obj), PATH_MAX - 1); target_dir[PATH_MAX - 1] = '\0'; if (strcmp(target_dir, ".") == 0) { target_dir[0] = '*'; target_dir[1] = '\0'; } glob_t results; struct stat file_stat; char mod_time[20], create_time[20]; if (glob(target_dir, GLOB_TILDE, NULL, &results) != 0) { return strdup("[]"); } json_object *json_array = json_object_new_array(); for (size_t i = 0; i < results.gl_pathc; i++) { const char *file_path = results.gl_pathv[i]; if (stat(file_path, &file_stat) == -1) continue; format_time(file_stat.st_mtime, mod_time, sizeof(mod_time)); format_time(file_stat.st_ctime, create_time, sizeof(create_time)); 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)); json_object_object_add(json_entry, "creation_date", json_object_new_string(create_time)); 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)); json_object_array_add(json_array, json_entry); } globfree(&results); char *result = strdup(json_object_to_json_string_ext(json_array, JSON_C_TO_STRING_PRETTY)); json_object_put(json_array); return result; } static struct json_object *directory_glob_get_description(void) { struct json_object *root = json_object_new_object(); json_object_object_add(root, "type", json_object_new_string("function")); struct json_object *function = json_object_new_object(); json_object_object_add(function, "name", json_object_new_string("directory_glob")); json_object_object_add(function, "description", json_object_new_string("List the contents of a specified directory in glob format. Result is a JSON array containing objects with keys: name, modification_date(iso), creation_date(iso), type, and size_bytes.")); struct json_object *parameters = json_object_new_object(); json_object_object_add(parameters, "type", json_object_new_string("object")); struct json_object *properties = json_object_new_object(); struct json_object *directory = json_object_new_object(); json_object_object_add(directory, "type", json_object_new_string("string")); json_object_object_add(directory, "description", json_object_new_string("Path to the directory to list in glob format.")); json_object_object_add(properties, "path", directory); json_object_object_add(parameters, "properties", properties); struct json_object *required = json_object_new_array(); json_object_array_add(required, json_object_new_string("path")); json_object_object_add(parameters, "required", required); json_object_object_add(parameters, "additionalProperties", json_object_new_boolean(0)); json_object_object_add(function, "parameters", parameters); r_config_handle cfg = r_config_get_instance(); if (r_config_use_strict(cfg)) { json_object_object_add(function, "strict", json_object_new_boolean(1)); } json_object_object_add(root, "function", function); return root; } static void mkdir_print_action(const char *name, struct json_object *args) { (void)name; if (!args) return; struct json_object *path; if (json_object_object_get_ex(args, "path", &path)) { fprintf(stderr, " -> Creating directory: %s\n", json_object_get_string(path)); } } static char *mkdir_execute(tool_t *self, struct json_object *args) { (void)self; struct json_object *path_obj; if (!json_object_object_get_ex(args, "path", &path_obj)) { return strdup("Error: missing 'path' argument"); } return make_dir_recursive(json_object_get_string(path_obj)); } static struct json_object *mkdir_get_description(void) { struct json_object *root = json_object_new_object(); json_object_object_add(root, "type", json_object_new_string("function")); struct json_object *function = json_object_new_object(); json_object_object_add(function, "name", json_object_new_string("mkdir")); json_object_object_add(function, "description", json_object_new_string("Creates a new directory with the specified path.")); struct json_object *parameters = json_object_new_object(); json_object_object_add(parameters, "type", json_object_new_string("object")); struct json_object *properties = 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, "description", json_object_new_string("Path of the directory to create.")); json_object_object_add(properties, "path", path); json_object_object_add(parameters, "properties", properties); struct json_object *required = json_object_new_array(); json_object_array_add(required, json_object_new_string("path")); json_object_object_add(parameters, "required", required); json_object_object_add(parameters, "additionalProperties", json_object_new_boolean(0)); json_object_object_add(function, "parameters", parameters); r_config_handle cfg = r_config_get_instance(); if (r_config_use_strict(cfg)) { json_object_object_add(function, "strict", json_object_new_boolean(1)); } json_object_object_add(root, "function", function); return root; } static void chdir_print_action(const char *name, struct json_object *args) { (void)name; if (!args) return; struct json_object *path; if (json_object_object_get_ex(args, "path", &path)) { fprintf(stderr, " -> Changing directory: %s\n", json_object_get_string(path)); } } static char *chdir_execute(tool_t *self, struct json_object *args) { (void)self; struct json_object *path_obj; if (!json_object_object_get_ex(args, "path", &path_obj)) { return strdup("Error: missing 'path' argument"); } if (chdir(json_object_get_string(path_obj)) != 0) { return strdup("Failed to change directory!"); } return strdup("Directory successfully changed."); } static struct json_object *chdir_get_description(void) { struct json_object *root = json_object_new_object(); json_object_object_add(root, "type", json_object_new_string("function")); struct json_object *function = json_object_new_object(); json_object_object_add(function, "name", json_object_new_string("chdir")); json_object_object_add(function, "description", json_object_new_string("Changes the current working directory to the specified path. Call this function when `cd` is prompted.")); struct json_object *parameters = json_object_new_object(); json_object_object_add(parameters, "type", json_object_new_string("object")); struct json_object *properties = 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, "description", json_object_new_string("Path to change the current working directory to.")); json_object_object_add(properties, "path", path); json_object_object_add(parameters, "properties", properties); struct json_object *required = json_object_new_array(); json_object_array_add(required, json_object_new_string("path")); json_object_object_add(parameters, "required", required); json_object_object_add(parameters, "additionalProperties", json_object_new_boolean(0)); json_object_object_add(function, "parameters", parameters); r_config_handle cfg = r_config_get_instance(); if (r_config_use_strict(cfg)) { json_object_object_add(function, "strict", json_object_new_boolean(1)); } json_object_object_add(root, "function", function); return root; } static void getpwd_print_action(const char *name, struct json_object *args) { (void)name; (void)args; fprintf(stderr, " -> Getting current directory\n"); } static char *getpwd_execute(tool_t *self, struct json_object *args) { (void)self; (void)args; char *cwd = malloc(PATH_MAX); if (!cwd) return strdup("Failed to allocate memory for current working directory!"); if (!getcwd(cwd, PATH_MAX)) { free(cwd); return strdup("Failed to get current working directory!"); } return cwd; } static struct json_object *getpwd_get_description(void) { struct json_object *root = json_object_new_object(); json_object_object_add(root, "type", json_object_new_string("function")); struct json_object *function = json_object_new_object(); json_object_object_add(function, "name", json_object_new_string("getpwd")); json_object_object_add(function, "description", json_object_new_string("Returns the current working directory as a string.")); json_object_object_add(function, "parameters", json_object_new_null()); json_object_object_add(root, "function", function); return root; }