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