Compare commits

...

2 Commits

Author SHA1 Message Date
6ed9e9188e Added bash execution 2025-03-03 09:39:19 +01:00
a24253f236 Update. 2025-03-03 08:32:41 +01:00
3 changed files with 143 additions and 110 deletions

5
line.h
View File

@ -13,7 +13,7 @@
#include <string.h>
#include <stdbool.h>
#define HISTORY_FILE "~/.calpaca_history"
#define HISTORY_FILE ".r_history"
bool line_initialized = false;
@ -61,7 +61,6 @@ char* line_read(char* prefix) {
}
void line_add_history(char* data) {
read_history(HISTORY_FILE);
add_history(data);
write_history(HISTORY_FILE);
}
}

View File

@ -2,10 +2,8 @@
// This code provides functions to interact with OpenAI's APIs. It includes functionalities for fetching available models, system interactions, and engaging in chat-based conversations using the OpenAI API.
// Imports the "http" library for handling HTTP requests and the "chat" library for JSON handling related to chat content.
// MIT License: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, to deal in the Software without restriction, including 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.
@ -31,35 +29,28 @@ bool openai_system(char* content) {
return is_done;
}
struct json_object * chat_message(char * url, char * data){
printf("QQQ %s\n",data);
struct json_object* chat_message(char* url, char* data) {
char* result = curl_post(url, data);
printf("<<%s>>",result);
struct json_object* parsed_json = json_tokener_parse(result);
if (!parsed_json) {
fprintf(stderr, "Failed to parse JSON.\n");
fprintf(stderr, "%s\n", result);
return 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", result);
json_object_put(parsed_json);
return NULL;
}
struct json_object* first_choice = json_object_array_get_idx(choices_array, 0);
if (!first_choice) {
fprintf(stderr, "Failed to get the first element of 'choices'.\n");
json_object_put(parsed_json);
return NULL;
}
struct json_object* message_object;
struct json_object* message_object;
if (!json_object_object_get_ex(first_choice, "message", &message_object)) {
fprintf(stderr, "Failed to get 'message' object.\n");
json_object_put(parsed_json);
@ -71,38 +62,23 @@ struct json_object * chat_message(char * url, char * data){
char* openai_chat(char* role, char* content) {
char* url = "https://api.openai.com/v1/chat/completions";
char* data = chat_json(role, content);
json_object * message_object = chat_message(url, data);
struct json_object *tool_calls;
json_object* message_object = chat_message(url, 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);
// char* tool_calls_str = (char *)json_object_to_json_string(tool_calls);
json_object * tool_call_results = tools_execute(tool_calls);
json_object* tool_call_results = tools_execute(tool_calls);
int array_len = json_object_array_length(tool_call_results);
// message_add_tool_call(tool_call_results);
for(int i = 0; i < array_len; i++){
json_object * tool_call_result = json_object_array_get_idx(tool_call_results, i);
message_add_tool_call(tool_call_result);
for (int i = 0; i < array_len; i++) {
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);
char* tool_calls_result_str = chat_json(NULL, NULL);
message_object = chat_message(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"));
//message_add("assistant", content_str);
// free(data);
char* final_result = strdup(content_str);
return final_result;
return strdup(content_str);
}
#endif
#endif

200
tools.h
View File

@ -1,3 +1,11 @@
// Written by retoor@molodetz.nl
// This code defines functions for HTTP requests and structuring tool descriptions and executions in JSON format using the JSON-C library. It uses cURL for HTTP requests.
// Imports not part of the language itself: JSON-C (json-c/json.h, json-c/json_object.h) and a custom header "http_curl.h"
// MIT License
#ifndef R_TOOLS_H
#define R_TOOLS_H
@ -6,128 +14,178 @@
#include <string.h>
#include "http_curl.h"
struct json_object * tool_description_http_get();
struct json_object *tool_description_http_get();
struct json_object *tool_description_bash();
struct json_object * tools_descriptions(){
struct json_object *tools_descriptions() {
struct json_object *root = json_object_new_array();
json_object_array_add(root, tool_description_http_get());
json_object_array_add(root, tool_description_bash());
return root;
}
char * tool_function_http_get(char * url) {
char *tool_function_http_get(char *url) {
fprintf(stderr, "Tool http_get: %s\n", url);
return curl_get(url);
}
struct json_object * tool_description_http_get(){
// Create root object
char * tool_function_bash(char * command){
fprintf(stderr, "Tool bash: %s\n", command);
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 NULL;
}
// 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);
if (new_output == NULL) {
perror("realloc failed");
free(output);
pclose(fp);
return NULL;
}
output = new_output;
strcpy(output + total_size, buffer);
total_size += chunk_size;
}
pclose(fp);
return output;
}
struct json_object *tool_description_http_get() {
struct json_object *root = json_object_new_object();
json_object_object_add(root, "type", json_object_new_string("function"));
// Create function object
struct json_object *function = json_object_new_object();
json_object_object_add(function, "name", json_object_new_string("http_fetch"));
json_object_object_add(function, "description", json_object_new_string("Get the contents of an url."));
// Create parameters object
json_object_object_add(function, "description", json_object_new_string("Get the contents of a URL."));
struct json_object *parameters = json_object_new_object();
json_object_object_add(parameters, "type", json_object_new_string("object"));
// Create properties object
struct json_object *properties = json_object_new_object();
struct json_object *url = json_object_new_object();
json_object_object_add(url, "type", json_object_new_string("string"));
json_object_object_add(url, "description", json_object_new_string("fetch url contents."));
json_object_object_add(url, "description", json_object_new_string("Fetch URL contents."));
json_object_object_add(properties, "url", url);
json_object_object_add(parameters, "properties", properties);
// Add required array
struct json_object *required = json_object_new_array();
json_object_array_add(required, json_object_new_string("url"));
json_object_object_add(parameters, "required", required);
// Add additionalProperties as false
json_object_object_add(parameters, "additionalProperties", json_object_new_boolean(0));
// Add parameters to function object
json_object_object_add(function, "parameters", parameters);
// Add strict mode
json_object_object_add(function, "strict", json_object_new_boolean(1));
// Add function object to root
json_object_object_add(root, "function", function);
return root;
}
struct json_object * tools_execute(struct json_object * tools_array){
//struct json_object * tools_result = json_object_new_object();
struct json_object * tools_result_messages = json_object_new_array();
struct json_object *tool_description_bash() {
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("bash_execute"));
json_object_object_add(function, "description", json_object_new_string("Execute a bash command on user terminal."));
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 *url = json_object_new_object();
json_object_object_add(url, "type", json_object_new_string("string"));
json_object_object_add(url, "description", json_object_new_string("Bash command to execute."));
json_object_object_add(properties, "command", url);
json_object_object_add(parameters, "properties", properties);
struct json_object *required = json_object_new_array();
json_object_array_add(required, json_object_new_string("command"));
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 *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);
// Iterate over array
for (int i = 0; i < array_len; i++) {
struct json_object *obj = json_object_array_get_idx(tools_array, i);
struct json_object * tool_result = json_object_new_object();
struct json_object *tool_result = json_object_new_object();
json_object_object_add(tool_result, "tool_call_id", json_object_new_string(json_object_get_string(json_object_object_get(obj, "id"))));
json_object_object_add(tool_result, "tool_call_id",
json_object_new_string(json_object_get_string(
json_object_object_get(obj, "id"))));
json_object_object_add(tool_result, "role", json_object_new_string("tool"));
// Get "id"
struct json_object *id_obj;
if (json_object_object_get_ex(obj, "id", &id_obj)) {
printf("ID: %s\n", json_object_get_string(id_obj));
}
// Get "type"
struct json_object *type_obj;
if (json_object_object_get_ex(obj, "type", &type_obj)) {
printf("Type: %s\n", json_object_get_string(type_obj));
if (strcmp(json_object_get_string(type_obj), "function")) {
continue;
}
}
// Get "function" object
struct json_object *function_obj;
if (json_object_object_get_ex(obj, "function", &function_obj)) {
// Get function "name"
struct json_object *name_obj;
char * function_name = NULL;
char *function_name = NULL;
if (json_object_object_get_ex(function_obj, "name", &name_obj)) {
function_name = (char *)json_object_get_string(name_obj);
printf("Function Name: %s\n", json_object_get_string(name_obj));
}
// Get function "arguments"
if(!strcmp(function_name,"http_fetch")){
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;
if (json_object_object_get_ex(arguments, "url", &url_obj)) {
char * url = (char *)json_object_get_string(url_obj);
char * http_result = curl_get(url);
printf("URL: %s\n", json_object_get_string(url_obj));
printf("content: %s\n",http_result);
json_object_object_add(tool_result, "content", json_object_new_string(http_result));
if (!strcmp(function_name, "bash_execute")) {
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;
if (json_object_object_get_ex(arguments, "command", &url_obj)) {
char *url = (char *)json_object_get_string(url_obj);
char *http_result = tool_function_bash(url);
json_object_object_add(tool_result, "content", json_object_new_string(http_result));
}
}
printf("Function Arguments: %s\n", json_object_get_string(arguments_obj));
}
if (!strcmp(function_name, "http_fetch")) {
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;
if (json_object_object_get_ex(arguments, "url", &url_obj)) {
char *url = (char *)json_object_get_string(url_obj);
char *http_result = tool_function_http_get(url);
json_object_object_add(tool_result, "content", json_object_new_string(http_result));
}
}
}
json_object_array_add(tools_result_messages, tool_result);
}
printf("\n"); // Add spacing for readability
}
//json_object_object_add(tools_result, "messages", tools_result_messages);
return tools_result_messages;
}