Update.
This commit is contained in:
parent
2f8701fef3
commit
bee172c6eb
219
tools.h
219
tools.h
@ -23,6 +23,8 @@ struct json_object *tool_description_linux_terminal();
|
||||
struct json_object *tool_description_directory_glob();
|
||||
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();
|
||||
@ -31,7 +33,7 @@ struct json_object *tools_descriptions() {
|
||||
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_write_file());
|
||||
|
||||
json_object_array_add(root, tool_description_directory_rglob());
|
||||
|
||||
return root;
|
||||
}
|
||||
@ -75,6 +77,42 @@ char * tool_function_linux_terminal(char * command){
|
||||
return output ? output : strdup("");
|
||||
}
|
||||
|
||||
struct json_object *tool_description_directory_rglob() {
|
||||
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_rglob"));
|
||||
json_object_object_add(function, "description", json_object_new_string("Recursively 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);
|
||||
json_object_object_add(function, "strict", json_object_new_boolean(1));
|
||||
|
||||
json_object_object_add(root, "function", function);
|
||||
|
||||
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"));
|
||||
@ -203,6 +241,171 @@ void format_time(time_t raw_time, char *buffer, size_t size) {
|
||||
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;
|
||||
results.gl_pathc = 0;
|
||||
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
|
||||
|
||||
// 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));
|
||||
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));
|
||||
|
||||
// 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) {
|
||||
fprintf(stderr, "Tools directory_glob: %s\n", target_dir);
|
||||
glob_t results;
|
||||
@ -457,6 +660,20 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
json_object_array_add(tools_result_messages, tool_result);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user