Formatting.

This commit is contained in:
retoor 2025-03-28 06:56:36 +01:00
parent 1e62665d43
commit bff6e758bc
21 changed files with 2614 additions and 2351 deletions

64
auth.h
View File

@ -1,69 +1,65 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This source code retrieves an API key from environment variables or defaults to a hardcoded key if none are found. // This source code retrieves an API key from environment variables or defaults
// to a hardcoded key if none are found.
// Uses the C standard library functions from stdlib.h for environment management and stdio.h for error handling. // Uses the C standard library functions from stdlib.h for environment
// management and stdio.h for error handling.
// MIT License // MIT License
#ifndef R_AUTH_H #ifndef R_AUTH_H
#define R_AUTH_H #define R_AUTH_H
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
enum AUTH_TYPE { enum AUTH_TYPE { AUTH_TYPE_NONE, AUTH_TYPE_API_KEY, AUTH_TYPE_FREE };
AUTH_TYPE_NONE,
AUTH_TYPE_API_KEY,
AUTH_TYPE_FREE
};
int auth_type = AUTH_TYPE_NONE; int auth_type = AUTH_TYPE_NONE;
void auth_free(){ void auth_free() { auth_type = AUTH_TYPE_FREE; }
auth_type = AUTH_TYPE_FREE;
}
void auth_init() { void auth_init() {
char *api_key = NULL; char *api_key = NULL;
if(auth_type != AUTH_TYPE_FREE) { if (auth_type != AUTH_TYPE_FREE) {
api_key = getenv("R_KEY"); api_key = getenv("R_KEY");
if (api_key) { if (api_key) {
auth_type = AUTH_TYPE_API_KEY; auth_type = AUTH_TYPE_API_KEY;
return; return;
} }
api_key = getenv("OPENAI_API_KEY"); api_key = getenv("OPENAI_API_KEY");
if (api_key) { if (api_key) {
auth_type = AUTH_TYPE_API_KEY; auth_type = AUTH_TYPE_API_KEY;
return; return;
} }
} }
auth_type = AUTH_TYPE_FREE; auth_type = AUTH_TYPE_FREE;
return; return;
} }
const char *resolve_api_key() { const char *resolve_api_key() {
static char *api_key = NULL; static char *api_key = NULL;
if(auth_type != AUTH_TYPE_FREE) { if (auth_type != AUTH_TYPE_FREE) {
api_key = getenv("R_KEY"); api_key = getenv("R_KEY");
if (api_key) { if (api_key) {
auth_type = AUTH_TYPE_API_KEY; auth_type = AUTH_TYPE_API_KEY;
return api_key; return api_key;
} }
api_key = getenv("OPENAI_API_KEY"); api_key = getenv("OPENAI_API_KEY");
if (api_key) { if (api_key) {
auth_type = AUTH_TYPE_API_KEY; auth_type = AUTH_TYPE_API_KEY;
return api_key; return api_key;
} }
} }
auth_type = AUTH_TYPE_FREE; auth_type = AUTH_TYPE_FREE;
api_key = "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"; api_key = "sk-proj-d798HLfWYBeB9HT_o7isaY0s88631IaYhhOR5IVAd4D_fF-"
return api_key; "SQ5z46BCr8iDi1ang1rUmlagw55T3BlbkFJ6IOsqhAxNN9Zt6ERDBnv2p2HCc2fDgc"
"5DsNhPxdOzYb009J6CNd4wILPsFGEoUdWo4QrZ1eOkA";
return api_key;
} }
#endif #endif

View File

@ -1,15 +1,15 @@
#include "browse.h" #include "browse.h"
int main() { int main() {
char *query = "example"; char *query = "example";
char *result = get_news(query); char *result = get_news(query);
if (result) {
printf("Result: %s\n", result);
free(result); // Free the allocated memory for the result
} else {
printf("Failed to fetch news.\n");
}
return 0; if (result) {
printf("Result: %s\n", result);
free(result); // Free the allocated memory for the result
} else {
printf("Failed to fetch news.\n");
}
return 0;
} }

View File

@ -1,63 +1,63 @@
#include <string.h> #include "http_curl.h"
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <json-c/json.h> #include <json-c/json.h>
#include <json-c/json_util.h> #include <json-c/json_util.h>
#include "http_curl.h" #include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *url_encode(char *s) { return curl_easy_escape(NULL, s, 0); }
char * url_encode(char *s){ char *web_search_news(char *q) {
return curl_easy_escape(NULL, s, 0); char *news = malloc(4096);
} news[0] = 0;
char *q_encoded = url_encode(q);
sprintf(news,
"https://search.molodetz.nl/search?q=%s&format=json&categories=news",
q_encoded);
free(q_encoded);
char *ret = curl_get(news);
free(news);
json_object *json_ret = json_tokener_parse(ret);
char * web_search_news(char * q){ json_object *json_results = json_object_object_get(json_ret, "results");
char * news = malloc(4096); json_object *json_result = json_object_array_get_idx(json_results, 0);
news[0] = 0; if (!json_result) {
char * q_encoded = url_encode(q);
sprintf(news, "https://search.molodetz.nl/search?q=%s&format=json&categories=news",q_encoded);
free(q_encoded);
char * ret = curl_get(news);
free(news);
json_object * json_ret = json_tokener_parse(ret);
json_object * json_results = json_object_object_get(json_ret, "results");
json_object * json_result = json_object_array_get_idx(json_results, 0);
if(!json_result){
json_object_put(json_ret);
free(ret);
return web_search_news(q);
}
json_object_put(json_ret); json_object_put(json_ret);
return ret; free(ret);
return web_search_news(q);
}
json_object_put(json_ret);
return ret;
} }
char * web_search(char * q){ char *web_search(char *q) {
char * news = (char *)malloc(4096); char *news = (char *)malloc(4096);
news[0] = 0; news[0] = 0;
char * q_encoded = url_encode(q); char *q_encoded = url_encode(q);
sprintf(news, "https://search.molodetz.nl/search?q=%s&format=json",q_encoded); sprintf(news, "https://search.molodetz.nl/search?q=%s&format=json",
free(q_encoded); q_encoded);
char * ret = curl_get(news); free(q_encoded);
free(news); char *ret = curl_get(news);
json_object * json_ret = json_tokener_parse(ret); free(news);
json_object *json_ret = json_tokener_parse(ret);
json_object * json_results = json_object_object_get(json_ret, "results"); json_object *json_results = json_object_object_get(json_ret, "results");
json_object * json_result = json_object_array_get_idx(json_results, 0); json_object *json_result = json_object_array_get_idx(json_results, 0);
if(!json_result){ if (!json_result) {
json_object_put(json_ret);
free(ret);
return web_search(q);
}
json_object_put(json_ret); json_object_put(json_ret);
return ret; free(ret);
return web_search(q);
}
json_object_put(json_ret);
return ret;
} }
char * web_search_engine(char * q){ char *web_search_engine(char *q) {
char * searx = malloc(4096); char *searx = malloc(4096);
searx[0] = 0; searx[0] = 0;
sprintf(searx, "https://searx.molodetz.nl/search?q=%s&format=json", q); sprintf(searx, "https://searx.molodetz.nl/search?q=%s&format=json", q);
char * ret = curl_get(searx); char *ret = curl_get(searx);
free(searx); free(searx);
return ret; return ret;
} }

50
chat.h
View File

@ -1,8 +1,8 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This code defines functionality for creating and managing JSON-based chat prompts // This code defines functionality for creating and managing JSON-based chat
// using a specific AI model configuration, providing easy integration with message handling // prompts using a specific AI model configuration, providing easy integration
// and HTTP communication for dynamic applications. // with message handling and HTTP communication for dynamic applications.
// Non-standard imports: json-c library for handling JSON objects. // Non-standard imports: json-c library for handling JSON objects.
@ -15,8 +15,8 @@
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in all // The above copyright notice and this permission notice shall be included in
// copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -26,38 +26,42 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
#ifndef R_PROMPT_H #ifndef R_PROMPT_H
#define R_PROMPT_H #define R_PROMPT_H
#include "tools.h"
#include "auth.h" #include "auth.h"
#include <json-c/json.h>
#include "messages.h" #include "messages.h"
#include "r.h" #include "r.h"
#include "tools.h"
#include <json-c/json.h>
static json_object *_prompt = NULL; static json_object *_prompt = NULL;
void chat_free() { void chat_free() {
if (_prompt == NULL) return; if (_prompt == NULL)
json_object_put(_prompt); return;
_prompt = NULL; json_object_put(_prompt);
_prompt = NULL;
} }
char *chat_json(const char *role, const char *message) { char *chat_json(const char *role, const char *message) {
chat_free(); chat_free();
json_object *root_object = json_object_new_object(); json_object *root_object = json_object_new_object();
json_object_object_add(root_object, "model", json_object_new_string(get_prompt_model())); json_object_object_add(root_object, "model",
json_object_new_string(get_prompt_model()));
if (role != NULL && message != NULL) {
message_add(role, message);
json_object_object_add(root_object, "tools", tools_descriptions());
}
json_object_object_add(root_object, "messages", message_list()); if (role != NULL && message != NULL) {
// json_object_object_add(root_object, "max_tokens", json_object_new_int(prompt_max_tokens)); message_add(role, message);
json_object_object_add(root_object, "temperature", json_object_new_double(PROMPT_TEMPERATURE)); json_object_object_add(root_object, "tools", tools_descriptions());
}
return (char *)json_object_to_json_string_ext(root_object, JSON_C_TO_STRING_PRETTY); json_object_object_add(root_object, "messages", message_list());
// json_object_object_add(root_object, "max_tokens",
// json_object_new_int(prompt_max_tokens));
json_object_object_add(root_object, "temperature",
json_object_new_double(PROMPT_TEMPERATURE));
return (char *)json_object_to_json_string_ext(root_object,
JSON_C_TO_STRING_PRETTY);
} }
#endif #endif

View File

@ -1,59 +1,60 @@
#include <stdio.h>
#include "db_utils.h" #include "db_utils.h"
#include <stdio.h>
void db_initialize() { void db_initialize() {
sqlite3 *db; sqlite3 *db;
char *err_msg = 0; char *err_msg = 0;
int rc = sqlite3_open("database.db", &db); int rc = sqlite3_open("database.db", &db);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
return; return;
} }
const char *sql = "CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT);"; const char *sql =
rc = sqlite3_exec(db, sql, 0, 0, &err_msg); "CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT);";
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
sqlite3_free(err_msg); sqlite3_free(err_msg);
} }
sqlite3_close(db); sqlite3_close(db);
} }
void test_db_set() { void test_db_set() {
json_object *result = db_set("test_key", "test_value"); json_object *result = db_set("test_key", "test_value");
if (result) { if (result) {
printf("db_set: %s\n", json_object_get_string(result)); printf("db_set: %s\n", json_object_get_string(result));
json_object_put(result); json_object_put(result);
} else { } else {
printf("db_set failed\n"); printf("db_set failed\n");
} }
} }
void test_db_get() { void test_db_get() {
json_object *result = db_get("test_key"); json_object *result = db_get("test_key");
if (result) { if (result) {
printf("db_get: %s\n", json_object_to_json_string(result)); printf("db_get: %s\n", json_object_to_json_string(result));
json_object_put(result); json_object_put(result);
} else { } else {
printf("db_get failed\n"); printf("db_get failed\n");
} }
} }
void test_db_query() { void test_db_query() {
json_object *result = db_query("SELECT * FROM kv_store"); json_object *result = db_query("SELECT * FROM kv_store");
if (result) { if (result) {
printf("db_query: %s\n", json_object_to_json_string(result)); printf("db_query: %s\n", json_object_to_json_string(result));
json_object_put(result); json_object_put(result);
} else { } else {
printf("db_query failed\n"); printf("db_query failed\n");
} }
} }
int main() { int main() {
db_initialize(); db_initialize();
test_db_set(); test_db_set();
test_db_get(); test_db_get();
test_db_query(); test_db_query();
return 0; return 0;
} }

View File

@ -2,178 +2,190 @@
#define DB_UTILS_H #define DB_UTILS_H
#include "r.h" #include "r.h"
#include <sqlite3.h>
#include <json-c/json.h>
#include "utils.h" #include "utils.h"
#include <json-c/json.h>
#include <sqlite3.h>
json_object *db_execute(const char *query);
char *db_file_expanded() {
char *expanded = expand_home_directory(DB_FILE);
json_object* db_execute(const char *query); static char result[4096];
result[0] = 0;
char * db_file_expanded(){ strcpy(result, expanded);
char * expanded = expand_home_directory(DB_FILE); free(expanded);
static char result[4096]; return result;
result[0] = 0;
strcpy(result, expanded);
free(expanded);
return result;
} }
void db_initialize(); void db_initialize();
json_object * db_set(const char *key, const char *value); json_object *db_set(const char *key, const char *value);
json_object* db_get(const char *key); json_object *db_get(const char *key);
json_object* db_query(const char *query); json_object *db_query(const char *query);
void db_initialize() { void db_initialize() {
sqlite3 *db; sqlite3 *db;
char *err_msg = 0; char *err_msg = 0;
int rc = sqlite3_open(db_file_expanded(), &db); int rc = sqlite3_open(db_file_expanded(), &db);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
return; return;
} }
const char *sql = "CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT);"; const char *sql =
rc = sqlite3_exec(db, sql, 0, 0, &err_msg); "CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT);";
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
sqlite3_free(err_msg); sqlite3_free(err_msg);
} }
sqlite3_close(db); sqlite3_close(db);
} }
json_object *db_set(const char *key, const char *value) {
sqlite3 *db;
char *err_msg = 0;
int rc = sqlite3_open(db_file_expanded(), &db);
json_object * db_set(const char *key, const char *value) { if (rc != SQLITE_OK) {
sqlite3 *db; return NULL;
char *err_msg = 0; }
int rc = sqlite3_open(db_file_expanded(), &db);
if (rc != SQLITE_OK) { char *sql =
return NULL; sqlite3_mprintf("INSERT INTO kv_store (key, value) VALUES (%Q, %Q) ON "
} "CONFLICT(key) DO UPDATE SET value = %Q WHERE key = %Q",
key, value, value, key);
char *sql = sqlite3_mprintf("INSERT INTO kv_store (key, value) VALUES (%Q, %Q) ON CONFLICT(key) DO UPDATE SET value = %Q WHERE key = %Q", key, value, value,key); rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
rc = sqlite3_exec(db, sql, 0, 0, &err_msg); sqlite3_free(sql);
sqlite3_free(sql);
if (rc != SQLITE_OK) {
sqlite3_free(err_msg);
sqlite3_close(db);
return NULL;
}
if (rc != SQLITE_OK) {
sqlite3_free(err_msg);
sqlite3_close(db); sqlite3_close(db);
return json_object_new_string("Success"); return NULL;
}
sqlite3_close(db);
return json_object_new_string("Success");
} }
json_object* db_get(const char *key) { json_object *db_get(const char *key) {
sqlite3 *db; sqlite3 *db;
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
json_object *result = json_object_new_object(); json_object *result = json_object_new_object();
const char *value = NULL; const char *value = NULL;
int rc = sqlite3_open(db_file_expanded(), &db); int rc = sqlite3_open(db_file_expanded(), &db);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
return NULL; return NULL;
}
const char *sql = "SELECT value FROM kv_store WHERE key = ?";
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) == SQLITE_ROW) {
value = (const char *)sqlite3_column_text(stmt, 0);
}
if (value) {
json_object_object_add(result, "value", json_object_new_string(value));
} else {
json_object_object_add(result, "error",
json_object_new_string("Key not found"));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return result;
}
json_object *db_query(const char *query) {
sqlite3 *db;
sqlite3_stmt *stmt;
if (strncmp(query, "SELECT", 6)) {
return db_execute(query);
}
json_object *result = json_object_new_array();
int rc = sqlite3_open(db_file_expanded(), &db);
if (rc != SQLITE_OK) {
return NULL;
}
sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
while (sqlite3_step(stmt) == SQLITE_ROW) {
json_object *row = json_object_new_object();
for (int i = 0; i < sqlite3_column_count(stmt); i++) {
const char *col_name = sqlite3_column_name(stmt, i);
switch (sqlite3_column_type(stmt, i)) {
case SQLITE_INTEGER:
json_object_object_add(
row, col_name,
json_object_new_int64(sqlite3_column_int64(stmt, i)));
break;
case SQLITE_FLOAT:
json_object_object_add(
row, col_name,
json_object_new_double(sqlite3_column_double(stmt, i)));
break;
case SQLITE_TEXT:
json_object_object_add(
row, col_name,
json_object_new_string((const char *)sqlite3_column_text(stmt, i)));
break;
case SQLITE_BLOB:
json_object_object_add(row, col_name,
json_object_new_string_len(
(const char *)sqlite3_column_blob(stmt, i),
sqlite3_column_bytes(stmt, i)));
break;
case SQLITE_NULL:
default:
json_object_object_add(row, col_name, json_object_new_string("NULL"));
break;
}
} }
json_object_array_add(result, row);
}
const char *sql = "SELECT value FROM kv_store WHERE key = ?"; sqlite3_finalize(stmt);
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); sqlite3_close(db);
sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) == SQLITE_ROW) { return result;
value = (const char *)sqlite3_column_text(stmt, 0); }
}
if (value) { json_object *db_execute(const char *query) {
json_object_object_add(result, "value", json_object_new_string(value)); sqlite3 *db;
} else { char *err_msg = 0;
json_object_object_add(result, "error", json_object_new_string("Key not found")); int rc = sqlite3_open(db_file_expanded(), &db);
} json_object *result = json_object_new_object();
sqlite3_finalize(stmt); if (rc != SQLITE_OK) {
sqlite3_close(db); json_object_object_add(result, "error",
json_object_new_string("Cannot open database"));
return result; return result;
}
rc = sqlite3_exec(db, query, 0, 0, &err_msg);
if (rc != SQLITE_OK) {
json_object_object_add(result, "error", json_object_new_string(err_msg));
sqlite3_free(err_msg);
} else {
json_object_object_add(
result, "success",
json_object_new_string("Query executed successfully"));
}
sqlite3_close(db);
return result;
} }
json_object* db_query(const char *query) { char *db_get_schema() {
sqlite3 *db; json_object *tables =
sqlite3_stmt *stmt; db_query("SELECT * FROM sqlite_master WHERE type='table'");
char *result = strdup(json_object_get_string(tables));
if(strncmp(query, "SELECT", 6)){ json_object_put(tables);
return db_execute(query); return result;
}
json_object *result = json_object_new_array();
int rc = sqlite3_open(db_file_expanded(), &db);
if (rc != SQLITE_OK) {
return NULL;
}
sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
while (sqlite3_step(stmt) == SQLITE_ROW) {
json_object *row = json_object_new_object();
for (int i = 0; i < sqlite3_column_count(stmt); i++) {
const char *col_name = sqlite3_column_name(stmt, i);
switch (sqlite3_column_type(stmt, i)) {
case SQLITE_INTEGER:
json_object_object_add(row, col_name, json_object_new_int64(sqlite3_column_int64(stmt, i)));
break;
case SQLITE_FLOAT:
json_object_object_add(row, col_name, json_object_new_double(sqlite3_column_double(stmt, i)));
break;
case SQLITE_TEXT:
json_object_object_add(row, col_name, json_object_new_string((const char *)sqlite3_column_text(stmt, i)));
break;
case SQLITE_BLOB:
json_object_object_add(row, col_name, json_object_new_string_len((const char *)sqlite3_column_blob(stmt, i), sqlite3_column_bytes(stmt, i)));
break;
case SQLITE_NULL:
default:
json_object_object_add(row, col_name, json_object_new_string("NULL"));
break;
}
}
json_object_array_add(result, row);
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return result;
}
json_object* db_execute(const char *query) {
sqlite3 *db;
char *err_msg = 0;
int rc = sqlite3_open(db_file_expanded(), &db);
json_object *result = json_object_new_object();
if (rc != SQLITE_OK) {
json_object_object_add(result, "error", json_object_new_string("Cannot open database"));
return result;
}
rc = sqlite3_exec(db, query, 0, 0, &err_msg);
if (rc != SQLITE_OK) {
json_object_object_add(result, "error", json_object_new_string(err_msg));
sqlite3_free(err_msg);
} else {
json_object_object_add(result, "success", json_object_new_string("Query executed successfully"));
}
sqlite3_close(db);
return result;
}
char * db_get_schema(){
json_object * tables =db_query("SELECT * FROM sqlite_master WHERE type='table'");
char * result = strdup(json_object_get_string(tables));
json_object_put(tables);
return result;
} }
#endif #endif

View File

@ -1,8 +1,12 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This code defines a simple HTTP client using libcurl in C. It provides functions for executing POST and GET HTTP requests with JSON data, including authorization via a bearer token. The functions `curl_post` and `curl_get` handle these operations and return the server's response as a string. // This code defines a simple HTTP client using libcurl in C. It provides
// functions for executing POST and GET HTTP requests with JSON data, including
// authorization via a bearer token. The functions `curl_post` and `curl_get`
// handle these operations and return the server's response as a string.
// Uses libcurl for HTTP requests and includes a custom "auth.h" for API key resolution. // Uses libcurl for HTTP requests and includes a custom "auth.h" for API key
// resolution.
// MIT License // MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
@ -11,101 +15,103 @@
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // 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 // 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 // notice and this permission notice shall be included in all copies or
// portions of the Software. The Software is provided "as is", without warranty of // substantial portions of the Software. The Software is provided "as is",
// any kind, express or implied, including but not limited to the warranties of // without warranty of any kind, express or implied, including but not limited
// merchantability, fitness for a particular purpose and noninfringement. In no // to the warranties of merchantability, fitness for a particular purpose and
// event shall the authors or copyright holders be liable for any claim, damages // noninfringement. In no event shall the authors or copyright holders be liable
// or other liability, whether in an action of contract, tort or otherwise, arising // for any claim, damages or other liability, whether in an action of contract,
// from, out of or in connection with the software or the use or other dealings in // tort or otherwise, arising from, out of or in connection with the software or
// the Software. // the use or other dealings in the Software.
#ifndef HTTP_CURL #ifndef HTTP_CURL
#define HTTP_CURL #define HTTP_CURL
#include "auth.h"
#include <curl/curl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <curl/curl.h>
#include "auth.h"
struct ResponseBuffer { struct ResponseBuffer {
char *data; char *data;
size_t size; size_t size;
}; };
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { static size_t WriteCallback(void *contents, size_t size, size_t nmemb,
size_t total_size = size * nmemb; void *userp) {
struct ResponseBuffer *response = (struct ResponseBuffer *)userp; size_t total_size = size * nmemb;
char *ptr = realloc(response->data, response->size + total_size + 1); struct ResponseBuffer *response = (struct ResponseBuffer *)userp;
if (ptr == NULL) { char *ptr = realloc(response->data, response->size + total_size + 1);
fprintf(stderr, "Failed to allocate memory for response\n"); if (ptr == NULL) {
return 0; fprintf(stderr, "Failed to allocate memory for response\n");
} return 0;
response->data = ptr; }
memcpy(&(response->data[response->size]), contents, total_size); response->data = ptr;
response->size += total_size; memcpy(&(response->data[response->size]), contents, total_size);
response->data[response->size] = '\0'; response->size += total_size;
return total_size; response->data[response->size] = '\0';
return total_size;
} }
char *curl_post(const char *url, const char *data) { char *curl_post(const char *url, const char *data) {
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
struct ResponseBuffer response = {malloc(1), 0}; struct ResponseBuffer response = {malloc(1), 0};
if (!response.data) return NULL; if (!response.data)
curl = curl_easy_init();
if (curl) {
struct curl_slist *headers = NULL;
curl_easy_setopt(curl, CURLOPT_URL, url);
headers = curl_slist_append(headers, "Content-Type: application/json");
char bearer_header[1337];
sprintf(bearer_header, "Authorization: Bearer %s", resolve_api_key());
headers = curl_slist_append(headers, bearer_header);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "An error occurred: %s\n", curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return response.data;
}
return NULL; return NULL;
curl = curl_easy_init();
if (curl) {
struct curl_slist *headers = NULL;
curl_easy_setopt(curl, CURLOPT_URL, url);
headers = curl_slist_append(headers, "Content-Type: application/json");
char bearer_header[1337];
sprintf(bearer_header, "Authorization: Bearer %s", resolve_api_key());
headers = curl_slist_append(headers, bearer_header);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "An error occurred: %s\n", curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return response.data;
}
return NULL;
} }
char *curl_get(const char *url) { char *curl_get(const char *url) {
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
struct ResponseBuffer response = {malloc(1), 0}; struct ResponseBuffer response = {malloc(1), 0};
if (!response.data) return NULL; if (!response.data)
return NULL;
curl = curl_easy_init(); curl = curl_easy_init();
if (curl) { if (curl) {
struct curl_slist *headers = NULL; struct curl_slist *headers = NULL;
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];
sprintf(bearer_header, "Authorization: Bearer %s", resolve_api_key()); sprintf(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);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
if (res != CURLE_OK) { if (res != CURLE_OK) {
fprintf(stderr, "An error occurred: %s\n", curl_easy_strerror(res)); fprintf(stderr, "An error occurred: %s\n", curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
} }
return response.data; curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return response.data;
} }
#endif #endif

228
indexer.h
View File

@ -1,133 +1,157 @@
#include <dirent.h>
#include <json-c/json.h>
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <dirent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <time.h> #include <time.h>
#include <json-c/json.h>
#include <limits.h>
#include <unistd.h> #include <unistd.h>
#define MAX_FILES 20000 #define MAX_FILES 20000
#define MAX_PATH 4096 #define MAX_PATH 4096
static const char *extensions[] = {".c", ".cpp", ".h", ".py", ".java", ".js", ".mk", ".html", "Makefile", ".css", ".json", ".cs", ".csproj", ".sln", ".toml",".rs"}; static const char *extensions[] = {
static size_t ext_count = sizeof(extensions) / sizeof(extensions[0]); // Updated count to reflect the new number of extensions ".c", ".cpp", ".h", ".py", ".java", ".js", ".mk", ".html",
"Makefile", ".css", ".json", ".cs", ".csproj", ".sln", ".toml", ".rs"};
static size_t ext_count =
sizeof(extensions) /
sizeof(
extensions[0]); // Updated count to reflect the new number of extensions
typedef struct { typedef struct {
char name[MAX_PATH]; char name[MAX_PATH];
char modification_date[20]; char modification_date[20];
char creation_date[20]; char creation_date[20];
char type[10]; char type[10];
size_t size_bytes; size_t size_bytes;
} FileInfo; } FileInfo;
FileInfo file_list[MAX_FILES]; FileInfo file_list[MAX_FILES];
size_t file_count = 0; size_t file_count = 0;
int is_valid_extension(const char *filename, const char *extensions[], size_t ext_count) { int is_valid_extension(const char *filename, const char *extensions[],
const char *dot = strrchr(filename, '.'); size_t ext_count) {
if(!dot){ const char *dot = strrchr(filename, '.');
dot = filename; if (!dot) {
} dot = filename;
for (size_t i = 0; i < ext_count; i++) { }
if (strcmp(dot, extensions[i]) == 0) { for (size_t i = 0; i < ext_count; i++) {
return 1; if (strcmp(dot, extensions[i]) == 0) {
} return 1;
} }
return 0; }
return 0;
} }
int is_ignored_directory(const char *dir_name) { int is_ignored_directory(const char *dir_name) {
const char *ignored_dirs[] = {"env", ".venv", "node_modules", "venv", "virtualenv"}; const char *ignored_dirs[] = {"env", ".venv", "node_modules", "venv",
for (size_t i = 0; i < sizeof(ignored_dirs) / sizeof(ignored_dirs[0]); i++) { "virtualenv"};
if (strcmp(dir_name, ignored_dirs[i]) == 0) { for (size_t i = 0; i < sizeof(ignored_dirs) / sizeof(ignored_dirs[0]); i++) {
return 1; if (strcmp(dir_name, ignored_dirs[i]) == 0) {
} return 1;
} }
return 0; }
return 0;
} }
void get_file_info(const char *path) { void get_file_info(const char *path) {
struct stat file_stat; struct stat file_stat;
if (stat(path, &file_stat) == 0) { if (stat(path, &file_stat) == 0) {
FileInfo info; FileInfo info;
strncpy(info.name, path, MAX_PATH - 1); // Copy with one less to leave space for null terminator strncpy(info.name, path,
info.name[MAX_PATH - 1] = '\0'; // Ensure null termination MAX_PATH -
strftime(info.modification_date, sizeof(info.modification_date), "%Y-%m-%d %H:%M:%S", localtime(&file_stat.st_mtime)); 1); // Copy with one less to leave space for null terminator
strftime(info.creation_date, sizeof(info.creation_date), "%Y-%m-%d %H:%M:%S", localtime(&file_stat.st_ctime)); info.name[MAX_PATH - 1] = '\0'; // Ensure null termination
strncpy(info.type, S_ISDIR(file_stat.st_mode) ? "directory" : "file", 10); strftime(info.modification_date, sizeof(info.modification_date),
info.type[9] = '\0'; // Ensure null termination "%Y-%m-%d %H:%M:%S", localtime(&file_stat.st_mtime));
info.size_bytes = file_stat.st_size; strftime(info.creation_date, sizeof(info.creation_date),
file_list[file_count++] = info; "%Y-%m-%d %H:%M:%S", localtime(&file_stat.st_ctime));
} strncpy(info.type, S_ISDIR(file_stat.st_mode) ? "directory" : "file", 10);
info.type[9] = '\0'; // Ensure null termination
info.size_bytes = file_stat.st_size;
file_list[file_count++] = info;
}
} }
char* index_directory(const char *dir_path) { char *index_directory(const char *dir_path) {
DIR *dir = opendir(dir_path); DIR *dir = opendir(dir_path);
struct dirent *entry; struct dirent *entry;
if (dir == NULL) { if (dir == NULL) {
perror("Failed to open directory"); perror("Failed to open directory");
return NULL; return NULL;
} }
json_object *jarray = json_object_new_array(); json_object *jarray = json_object_new_array();
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
if (entry->d_name[0] == '.' || is_ignored_directory(entry->d_name)) {
continue;
}
char full_path[MAX_PATH];
snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, entry->d_name);
if (entry->d_type == DT_DIR) {
char *subdir_json = index_directory(full_path);
if (subdir_json) {
json_object *jsubdir = json_object_new_string(subdir_json);
json_object_array_add(jarray, jsubdir);
free(subdir_json);
}
} else if (is_valid_extension(entry->d_name, extensions, ext_count)) {
get_file_info(full_path);
json_object *jfile = json_object_new_object();
json_object_object_add(jfile, "file_name", json_object_new_string(file_list[file_count - 1].name));
json_object_object_add(jfile, "modification_date", json_object_new_string(file_list[file_count - 1].modification_date));
json_object_object_add(jfile, "creation_date", json_object_new_string(file_list[file_count - 1].creation_date));
json_object_object_add(jfile, "type", json_object_new_string(file_list[file_count - 1].type));
json_object_object_add(jfile, "size_bytes", json_object_new_int64(file_list[file_count - 1].size_bytes));
// Read the file contents while ((entry = readdir(dir)) != NULL) {
FILE *fp = fopen(file_list[file_count - 1].name, "r"); if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
if (fp != NULL) { if (entry->d_name[0] == '.' || is_ignored_directory(entry->d_name)) {
fseek(fp, 0, SEEK_END); continue;
long length = ftell(fp); }
fseek(fp, 0, SEEK_SET); char full_path[MAX_PATH];
char *content = malloc(length + 1); snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, entry->d_name);
if (content) { if (entry->d_type == DT_DIR) {
size_t bytesRead = fread(content, 1, length, fp); char *subdir_json = index_directory(full_path);
if (bytesRead != length) { if (subdir_json) {
free(content); json_object *jsubdir = json_object_new_string(subdir_json);
content = NULL; json_object_array_add(jarray, jsubdir);
json_object_object_add(jfile, "file_current_content_data", json_object_new_string("Error reading file")); free(subdir_json);
} else {
content[length] = '\0'; // Null-terminate the string
//json_object_object_add(jfile, "file_current_content_data", json_object_new_string(content));
}
free(content);
}
fclose(fp);
} else {
//json_object_object_add(jfile, "content", json_object_new_string("Unable to read file"));
}
json_object_array_add(jarray, jfile);
}
} }
} } else if (is_valid_extension(entry->d_name, extensions, ext_count)) {
closedir(dir); get_file_info(full_path);
json_object *jfile = json_object_new_object();
json_object_object_add(
jfile, "file_name",
json_object_new_string(file_list[file_count - 1].name));
json_object_object_add(
jfile, "modification_date",
json_object_new_string(
file_list[file_count - 1].modification_date));
json_object_object_add(
jfile, "creation_date",
json_object_new_string(file_list[file_count - 1].creation_date));
json_object_object_add(
jfile, "type",
json_object_new_string(file_list[file_count - 1].type));
json_object_object_add(
jfile, "size_bytes",
json_object_new_int64(file_list[file_count - 1].size_bytes));
char *result = strdup(json_object_to_json_string(jarray)); // Read the file contents
json_object_put(jarray); FILE *fp = fopen(file_list[file_count - 1].name, "r");
return result; if (fp != NULL) {
fseek(fp, 0, SEEK_END);
long length = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *content = malloc(length + 1);
if (content) {
size_t bytesRead = fread(content, 1, length, fp);
if (bytesRead != length) {
free(content);
content = NULL;
json_object_object_add(
jfile, "file_current_content_data",
json_object_new_string("Error reading file"));
} else {
content[length] = '\0'; // Null-terminate the string
// json_object_object_add(jfile, "file_current_content_data",
// json_object_new_string(content));
}
free(content);
}
fclose(fp);
} else {
// json_object_object_add(jfile, "content",
// json_object_new_string("Unable to read file"));
}
json_object_array_add(jarray, jfile);
}
}
}
closedir(dir);
char *result = strdup(json_object_to_json_string(jarray));
json_object_put(jarray);
return result;
} }

View File

@ -1,47 +1,50 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This source code extracts URLs from an input string and replaces them inline with their respective content in Markdown style. // This source code extracts URLs from an input string and replaces them inline
// with their respective content in Markdown style.
// Imports used: regex.h for regular expression operations, http.h and url.h for HTTP and URL-related utility functions. // Imports used: regex.h for regular expression operations, http.h and url.h for
// HTTP and URL-related utility functions.
// MIT License // MIT License
#include <regex.h>
#include "http.h" #include "http.h"
#include "url.h" #include "url.h"
#include <regex.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
void extract_urls(const char *input, char **urls, int *url_count) { void extract_urls(const char *input, char **urls, int *url_count) {
const char *pattern = "https?://[^ ]+"; const char *pattern = "https?://[^ ]+";
regex_t regex; regex_t regex;
regcomp(&regex, pattern, REG_EXTENDED); regcomp(&regex, pattern, REG_EXTENDED);
regmatch_t match; regmatch_t match;
const char *cursor = input; const char *cursor = input;
*url_count = 0; *url_count = 0;
while (!regexec(&regex, cursor, 1, &match, 0)) { while (!regexec(&regex, cursor, 1, &match, 0)) {
int length = match.rm_eo - match.rm_so; int length = match.rm_eo - match.rm_so;
urls[*url_count] = strndup(cursor + match.rm_so, length); urls[*url_count] = strndup(cursor + match.rm_so, length);
cursor += match.rm_eo; cursor += match.rm_eo;
(*url_count)++; (*url_count)++;
} }
regfree(&regex); regfree(&regex);
} }
void inplace_urls_markdown_style(char **input, char **urls, char **contents, int url_count) { void inplace_urls_markdown_style(char **input, char **urls, char **contents,
for (int i = 0; i < url_count; i++) { int url_count) {
char *found = strstr(*input, urls[i]); for (int i = 0; i < url_count; i++) {
if (found) { char *found = strstr(*input, urls[i]);
char *new_text = (char *)malloc(strlen(*input) + strlen(contents[i]) - strlen(urls[i]) + 1); if (found) {
strncpy(new_text, *input, found - *input); char *new_text = (char *)malloc(strlen(*input) + strlen(contents[i]) -
new_text[found - *input] = '\0'; strlen(urls[i]) + 1);
strcat(new_text, contents[i]); strncpy(new_text, *input, found - *input);
strcat(new_text, found + strlen(urls[i])); new_text[found - *input] = '\0';
strcat(new_text, contents[i]);
strcat(new_text, found + strlen(urls[i]));
free(*input); free(*input);
*input = new_text; *input = new_text;
}
} }
}
} }

138
line.h
View File

@ -1,102 +1,108 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This source code provides command-line input functionalities with autocomplete and history features using the readline library. It allows users to complete commands and manage input history. // This source code provides command-line input functionalities with
// autocomplete and history features using the readline library. It allows users
// to complete commands and manage input history.
// External includes: // External includes:
// - <readline/readline.h> // - <readline/readline.h>
// - <readline/history.h> // - <readline/history.h>
// - <glob.h> // - <glob.h>
// 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. // 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.
#include <readline/readline.h>
#include <readline/history.h>
#include <string.h>
#include <stdbool.h>
#include <glob.h>
#include "utils.h" #include "utils.h"
#include <glob.h>
#include <readline/history.h>
#include <readline/readline.h>
#include <stdbool.h>
#include <string.h>
#define HISTORY_FILE "~/.r_history" #define HISTORY_FILE "~/.r_history"
bool line_initialized = false; bool line_initialized = false;
char *get_history_file() {
static char result[4096];
result[0] = 0;
char * get_history_file(){ char *expanded = expand_home_directory(HISTORY_FILE);
static char result[4096]; strcpy(result, expanded);
result[0] = 0; free(expanded);
return result;
char * expanded = expand_home_directory(HISTORY_FILE);
strcpy(result, expanded);
free(expanded);
return result;
} }
char* line_command_generator(const char* text, int state) { char *line_command_generator(const char *text, int state) {
static int list_index, len = 0; static int list_index, len = 0;
const char* commands[] = {"help", "exit", "list", "review", "refactor", "obfuscate", "!verbose","!dump", "!model","!debug", NULL}; const char *commands[] = {"help", "exit", "list", "review",
"refactor", "obfuscate", "!verbose", "!dump",
"!model", "!debug", NULL};
if (!state) { if (!state) {
list_index = 0; list_index = 0;
len = strlen(text); len = strlen(text);
}
while (commands[list_index]) {
const char *command = commands[list_index++];
if (strncmp(command, text, len) == 0) {
return strdup(command);
} }
}
while (commands[list_index]) { return NULL;
const char* command = commands[list_index++];
if (strncmp(command, text, len) == 0) {
return strdup(command);
}
}
return NULL;
} }
char* line_file_generator(const char* text, int state) { char *line_file_generator(const char *text, int state) {
static int list_index; static int list_index;
glob_t glob_result; glob_t glob_result;
char pattern[1024]; char pattern[1024];
if (!state) { if (!state) {
list_index = 0; list_index = 0;
snprintf(pattern, sizeof(pattern), "%s*", text); // Create a pattern for glob snprintf(pattern, sizeof(pattern), "%s*",
glob(pattern, GLOB_NOSORT, NULL, &glob_result); text); // Create a pattern for glob
} glob(pattern, GLOB_NOSORT, NULL, &glob_result);
}
if (list_index < glob_result.gl_pathc) { if (list_index < glob_result.gl_pathc) {
return strdup(glob_result.gl_pathv[list_index++]); return strdup(glob_result.gl_pathv[list_index++]);
} }
globfree(&glob_result); globfree(&glob_result);
return NULL; return NULL;
} }
char** line_command_completion(const char* text, int start, int end) { char **line_command_completion(const char *text, int start, int end) {
rl_attempted_completion_over = 1; rl_attempted_completion_over = 1;
// Check if the input is a file path // Check if the input is a file path
if (start > 0 && text[0] != ' ') { if (start > 0 && text[0] != ' ') {
return rl_completion_matches(text, line_file_generator); return rl_completion_matches(text, line_file_generator);
} }
return rl_completion_matches(text, line_command_generator); return rl_completion_matches(text, line_command_generator);
} }
void line_init() { void line_init() {
if (!line_initialized) { if (!line_initialized) {
rl_attempted_completion_function = line_command_completion; rl_attempted_completion_function = line_command_completion;
line_initialized = true; line_initialized = true;
read_history(get_history_file()); read_history(get_history_file());
} }
} }
char* line_read(char* prefix) { char *line_read(char *prefix) {
char* data = readline(prefix); char *data = readline(prefix);
if (!(data && *data)) { if (!(data && *data)) {
free(data); free(data);
return NULL; return NULL;
} }
return data; return data;
} }
void line_add_history(char* data) { void line_add_history(char *data) {
add_history(data); add_history(data);
write_history(get_history_file()); write_history(get_history_file());
} }

529
main.c
View File

@ -1,6 +1,9 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This source code initializes a command-line application that uses OpenAI for chat interactions, handles user inputs, and can start a simple HTTP server with CGI support. The code allows command execution, markdown parsing, and OpenAI chat integration. // This source code initializes a command-line application that uses OpenAI for
// chat interactions, handles user inputs, and can start a simple HTTP server
// with CGI support. The code allows command execution, markdown parsing, and
// OpenAI chat integration.
// External imports used in this code: // External imports used in this code:
// - openai.h // - openai.h
@ -28,24 +31,22 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#include "r.h" #include "r.h"
#include <signal.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <signal.h>
#include "openai.h"
#include "markdown.h"
#include "line.h" #include "line.h"
#include "markdown.h"
#include "openai.h"
#include "utils.h"
#include <locale.h> #include <locale.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "utils.h"
#include "db_utils.h" #include "db_utils.h"
@ -56,311 +57,315 @@ bool API_MODE = false;
void help(); void help();
void render(char *); void render(char *);
bool openai_include(char *path); bool openai_include(char *path);
char * strreplace(char * content, char * what, char * with); char *strreplace(char *content, char *what, char *with);
char * get_prompt_from_stdin(char * prompt) { char *get_prompt_from_stdin(char *prompt) {
int index = 0; int index = 0;
prompt[index] = '\0'; prompt[index] = '\0';
char c = 0; char c = 0;
while ((c = getchar()) != EOF) { while ((c = getchar()) != EOF) {
prompt[index++] = c; prompt[index++] = c;
} }
prompt[index++] = '\0'; prompt[index++] = '\0';
return prompt; return prompt;
} }
char *get_prompt_from_args(int c, char **argv) { char *get_prompt_from_args(int c, char **argv) {
char *prompt = (char *)malloc(1024 * 1024 * 10 + 1); char *prompt = (char *)malloc(1024 * 1024 * 10 + 1);
char *system = (char *)malloc(1024*1024); char *system = (char *)malloc(1024 * 1024);
system[0] = 0; system[0] = 0;
prompt[0] = 0; prompt[0] = 0;
bool get_from_std_in = false; bool get_from_std_in = false;
for (int i = 1; i < c; i++) { for (int i = 1; i < c; i++) {
if (!strcmp(argv[i],"--stdin")){ if (!strcmp(argv[i], "--stdin")) {
fprintf(stderr, "%s\n", "Reading from stdin."); fprintf(stderr, "%s\n", "Reading from stdin.");
get_from_std_in = true; get_from_std_in = true;
}else if(!strcmp(argv[i],"--verbose")){ } else if (!strcmp(argv[i], "--verbose")) {
is_verbose = true; is_verbose = true;
}
else if(!strcmp(argv[i],"--py")){
if(i+1 <= c){
char * py_file_path = expand_home_directory(argv[i+1]);
fprintf(stderr, "Including \"%s\".\n", py_file_path);
openai_include(py_file_path);
free(py_file_path);
//char * file_content = read_file(py_file_path);
//plugin_run(file_content);
i++;
}
}else if (!strcmp(argv[i],"--free")){
auth_free();
continue;
}
else if(!strcmp(argv[i],"--context")){
if(i+1 <= c){
char * context_file_path = argv[i+1];
fprintf(stderr, "Including \"%s\".\n", context_file_path);
openai_include(context_file_path);
i++;
}
}else if(!strcmp(argv[i],"--api")){
API_MODE = true;
}else if(!strcmp(argv[i], "--nh")){
SYNTAX_HIGHLIGHT_ENABLED = false;
fprintf(stderr, "%s\n", "Syntax highlighting disabled.");
}else if (!get_from_std_in){
strcat(system, argv[i]);
if (i < c - 1) {
strcat(system, " ");
} else {
strcat(system, ".");
}
}
} }
if(get_from_std_in){ else if (!strcmp(argv[i], "--py")) {
if(*system){ if (i + 1 <= c) {
openai_system(system); char *py_file_path = expand_home_directory(argv[i + 1]);
} fprintf(stderr, "Including \"%s\".\n", py_file_path);
free(system); openai_include(py_file_path);
prompt = get_prompt_from_stdin(prompt); free(py_file_path);
}else{ // char * file_content = read_file(py_file_path);
free(prompt); // plugin_run(file_content);
prompt = system; i++;
}
} else if (!strcmp(argv[i], "--free")) {
auth_free();
continue;
} }
if (!*prompt) { else if (!strcmp(argv[i], "--context")) {
free(prompt); if (i + 1 <= c) {
return NULL; char *context_file_path = argv[i + 1];
fprintf(stderr, "Including \"%s\".\n", context_file_path);
openai_include(context_file_path);
i++;
}
} else if (!strcmp(argv[i], "--api")) {
API_MODE = true;
} else if (!strcmp(argv[i], "--nh")) {
SYNTAX_HIGHLIGHT_ENABLED = false;
fprintf(stderr, "%s\n", "Syntax highlighting disabled.");
} else if (!get_from_std_in) {
strcat(system, argv[i]);
if (i < c - 1) {
strcat(system, " ");
} else {
strcat(system, ".");
}
} }
return prompt; }
if (get_from_std_in) {
if (*system) {
openai_system(system);
}
free(system);
prompt = get_prompt_from_stdin(prompt);
} else {
free(prompt);
prompt = system;
}
if (!*prompt) {
free(prompt);
return NULL;
}
return prompt;
} }
bool try_prompt(int argc, char *argv[]) { 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 != NULL) { if (prompt != NULL) {
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;
} }
void serve() { void serve() {
render("Starting server. *Put executables in a dir named cgi-bin and they will behave as web pages.*"); render("Starting server. *Put executables in a dir named cgi-bin and they "
int res = system("python3 -m http.server --cgi"); "will behave as web pages.*");
(void)res; int res = system("python3 -m http.server --cgi");
(void)res;
} }
char ** get_parameters(char * content, char * delimiter){ char **get_parameters(char *content, char *delimiter) {
char * start = NULL; char *start = NULL;
char ** parameters = NULL; //(char **)malloc(sizeof(char *) * 2); char **parameters = NULL; //(char **)malloc(sizeof(char *) * 2);
int count = 0; int count = 0;
while((start = strstr(content, delimiter)) != NULL){ while ((start = strstr(content, delimiter)) != NULL) {
start += 3; start += 3;
char * end = strstr(start, delimiter); char *end = strstr(start, delimiter);
char * parameter = (char *)malloc(end - start + 1); char *parameter = (char *)malloc(end - start + 1);
memcpy(parameter, start, end - start);
parameter[end - start] = '\0';
memcpy(parameter, start, end - start);
parameter[end - start] = '\0';
// printf("%s\n", parameter); // printf("%s\n", parameter);
content = end + 3; content = end + 3;
count+=1; count += 1;
parameters = (char **)realloc(parameters, sizeof(char *) * (1+count*2)); parameters = (char **)realloc(parameters, sizeof(char *) * (1 + count * 2));
parameters[count-1] = parameter; parameters[count - 1] = parameter;
parameters[count] = NULL; parameters[count] = NULL;
}
} return parameters;
return parameters;
} }
void render(char *content) void render(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); }
}
} }
void repl() { void repl() {
line_init(); line_init();
char *line = NULL; char *line = NULL;
//char *previous_line = NULL; // char *previous_line = NULL;
while (true) { while (true) {
line = line_read("> "); line = line_read("> ");
if (!line || !*line) { if (!line || !*line) {
continue; continue;
//line = previous_line; // line = previous_line;
}
if (!line || !*line)
continue;
// previous_line = line;
if(!strncmp(line,"!dump",5)){
printf("%s\n",message_json());
continue;
}
if(!strncmp(line,"!verbose",7)){
is_verbose = !is_verbose;
fprintf(stderr,"%s\n",is_verbose?"Verbose mode enabled":"Verbose mode disabled");
continue;
}
if (!strncmp(line, "!model", 6)) {
if(!strncmp(line+6," ",1)){
line = line+7;
set_prompt_model(line);
}
printf("%s\n",get_prompt_model());
continue;
}
if (!strncmp(line, "exit", 4)) {
exit(0);
}
if (!strncmp(line, "help", 4)) {
help();
continue;
}
if(!strncmp(line, "!debug", 6)){
r_malloc_stats();
continue;
}
while(line && *line != '\n'){
line_add_history(line);
char *response = openai_chat("user", line);
if(response){
render(response);
printf("\n");
if(strstr(response,"_STEP_")){
line = "continue";
}else{
line = NULL;
}
free(response);
}
}
} }
if (!line || !*line)
continue;
// previous_line = line;
if (!strncmp(line, "!dump", 5)) {
printf("%s\n", message_json());
continue;
}
if (!strncmp(line, "!verbose", 7)) {
is_verbose = !is_verbose;
fprintf(stderr, "%s\n",
is_verbose ? "Verbose mode enabled" : "Verbose mode disabled");
continue;
}
if (!strncmp(line, "!model", 6)) {
if (!strncmp(line + 6, " ", 1)) {
line = line + 7;
set_prompt_model(line);
}
printf("%s\n", get_prompt_model());
continue;
}
if (!strncmp(line, "exit", 4)) {
exit(0);
}
if (!strncmp(line, "help", 4)) {
help();
continue;
}
if (!strncmp(line, "!debug", 6)) {
r_malloc_stats();
continue;
}
while (line && *line != '\n') {
line_add_history(line);
char *response = openai_chat("user", line);
if (response) {
render(response);
printf("\n");
if (strstr(response, "_STEP_")) {
line = "continue";
} else {
line = NULL;
}
free(response);
}
}
}
} }
void help() { void help() {
char help_text[1024 * 1024] = {0}; char help_text[1024 * 1024] = {0};
char *template = "# Help\n" char *template =
"Written by retoor@molodetz.nl.\n\n" "# Help\n"
"## Features\n" "Written by retoor@molodetz.nl.\n\n"
" - navigate through history using `arrows`.\n" "## Features\n"
" - navigate through history with **recursive search** using `ctrl+r`.\n" " - navigate through history using `arrows`.\n"
" - **inception with python** for *incoming* and *outgoing* content.\n" " - navigate through history with **recursive search** using `ctrl+r`.\n"
" - markdown and **syntax highlighting**.\n" " - **inception with python** for *incoming* and *outgoing* content.\n"
" - **execute python commands** with prefix `!`\n" " - markdown and **syntax highlighting**.\n"
" - list files of the current work directory using `ls`.\n" " - **execute python commands** with prefix `!`\n"
" - type `serve` to start a web server with directory listing. Easy for network transfers.\n\n" " - list files of the current work directory using `ls`.\n"
"## Configuration\n" " - type `serve` to start a web server with directory listing. Easy for "
" - model temperature is %f.\n" "network transfers.\n\n"
" - model name is %s.\n" "## Configuration\n"
" - max tokens is %d.\n\n" " - model temperature is %f.\n"
"## In development\n" " - model name is %s.\n"
" - **google search** and actions with those results.\n" " - max tokens is %d.\n\n"
" - **reminders**.\n" "## In development\n"
" - predefined **templates** for **reviewing** / **refactoring** so you can personalize.\n"; " - **google search** and actions with those results.\n"
sprintf(help_text, template, PROMPT_TEMPERATURE, get_prompt_model(), prompt_max_tokens); " - **reminders**.\n"
render(help_text); " - predefined **templates** for **reviewing** / **refactoring** so you "
"can personalize.\n";
sprintf(help_text, template, PROMPT_TEMPERATURE, get_prompt_model(),
prompt_max_tokens);
render(help_text);
} }
char * strreplace(char * content, char * what, char * with){ char *strreplace(char *content, char *what, char *with) {
char * pos = strstr(content, what); char *pos = strstr(content, what);
if(!pos){ if (!pos) {
return strdup(content); return strdup(content);
} }
char * result = (char *)malloc(strlen(content) + strlen(with) + 5); char *result = (char *)malloc(strlen(content) + strlen(with) + 5);
memset(result, 0, strlen(content) + strlen(with) + 3); memset(result, 0, strlen(content) + strlen(with) + 3);
memcpy(result, content, pos - content); memcpy(result, content, pos - content);
memcpy(result + (pos - content), with, strlen(with)); memcpy(result + (pos - content), with, strlen(with));
memcpy(result + (pos - content) + strlen(with), pos + strlen(what), strlen(content) - (pos - content) - strlen(what) + 1); memcpy(result + (pos - content) + strlen(with), pos + strlen(what),
return result; strlen(content) - (pos - content) - strlen(what) + 1);
return result;
} }
char * linux_instructions = char *linux_instructions =
"You are a linux master and are able to transform the prompt of " "You are a linux master and are able to transform the prompt of "
"user into shell commands that will be executed on a debian " "user into shell commands that will be executed on a debian "
"based system. You can execute shell commands by responding with python code: " "based system. You can execute shell commands by responding with python "
"literally `\"\"\"!system\"\"\",\"\"\"`your shell command`\"\"\". Execute immediately. Read bash history file if you have to work with history."; "code: "
char * retoor_instructions = "If the user prompts with social talk, " "literally `\"\"\"!system\"\"\",\"\"\"`your shell command`\"\"\". Execute "
"respond like replica and emoji. Your name is retoor and made by molodetz. Be interested. Be creative."; "immediately. Read bash history file if you have to work with history.";
char *retoor_instructions =
"If the user prompts with social talk, "
"respond like replica and emoji. Your name is retoor and made by molodetz. "
"Be interested. Be creative.";
bool openai_include(char *path) { bool openai_include(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;
} }
void init() { void init() {
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};
sprintf(payload, "Your have a database that you can mutate using the query tool and the get and set tool. This is the schema in json format: %s. Dialect is sqlite.", schema); sprintf(payload,
free(schema); "Your have a database that you can mutate using the query tool and "
fprintf(stderr, "%s", "Loading... ⏳"); "the get and set tool. This is the schema in json format: %s. "
openai_system(payload); "Dialect is sqlite.",
if(!openai_include(".rcontext.txt")){ schema);
openai_include("~/.rcontext.txt"); free(schema);
} fprintf(stderr, "%s", "Loading... ⏳");
fprintf(stderr, "\r \r"); openai_system(payload);
if (!openai_include(".rcontext.txt")) {
openai_include("~/.rcontext.txt");
}
fprintf(stderr, "\r \r");
} }
void handle_sigint(int sig) { 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();
if (try_prompt(argc, argv)) if (try_prompt(argc, argv))
return 0;
repl();
return 0; return 0;
repl();
return 0;
} }

View File

@ -1,8 +1,11 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This program provides functionality to highlight the keywords in source code using ANSI color formatting and convert Markdown syntax into ANSI-colored text output. // 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. // Uses standard C libraries: <stdio.h>, <string.h>. Also utilizes ANSI escape
// codes for text formatting.
// MIT License: // MIT License:
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
@ -12,8 +15,8 @@
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in all // The above copyright notice and this permission notice shall be included in
// copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -23,9 +26,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdbool.h>
#define RESET "\033[0m" #define RESET "\033[0m"
#define BOLD "\033[1m" #define BOLD "\033[1m"
@ -35,153 +38,164 @@
#define FG_CYAN "\033[36m" #define FG_CYAN "\033[36m"
int is_keyword(const char *word) { int is_keyword(const char *word) {
const char *keywords[] = {
"int", "float", "double", "char", "void",
"if", "else", "while", "for", "return",
"struct", "printf",
// Rust keywords
"let", "fn", "impl", "match", "enum", "trait", "use", "mod", "pub", "const", "static",
// Python keywords
"def", "class", "import", "from", "as", "with", "try", "except", "finally", "lambda", "async", "await",
// Java keywords
"public", "private", "protected", "class", "interface", "extends", "implements", "new", "static", "final", "synchronized",
// JavaScript keywords
"var", "let", "const", "function", "async", "await", "if", "else", "switch", "case", "break", "continue", "return",
// C++ keywords
"namespace", "template", "typename", "class", "public", "private", "protected", "virtual", "override", "friend", "new",
// Go keywords
"package", "import", "func", "var", "const", "type", "interface", "struct", "go", "defer", "select",
// Bash keywords
"if", "then", "else", "elif", "fi", "case", "esac", "for", "while", "until", "do", "done", "function",
// C# keywords
"namespace", "using", "class", "interface", "public", "private", "protected", "static", "void", "new", "override"
};
for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) { const char *keywords[] = {
if (strcmp(word, keywords[i]) == 0) { "int", "float", "double", "char", "void", "if", "else", "while", "for",
return 1; "return", "struct", "printf",
} // Rust keywords
"let", "fn", "impl", "match", "enum", "trait", "use", "mod", "pub",
"const", "static",
// Python keywords
"def", "class", "import", "from", "as", "with", "try", "except",
"finally", "lambda", "async", "await",
// Java keywords
"public", "private", "protected", "class", "interface", "extends",
"implements", "new", "static", "final", "synchronized",
// JavaScript keywords
"var", "let", "const", "function", "async", "await", "if", "else",
"switch", "case", "break", "continue", "return",
// C++ keywords
"namespace", "template", "typename", "class", "public", "private",
"protected", "virtual", "override", "friend", "new",
// Go keywords
"package", "import", "func", "var", "const", "type", "interface",
"struct", "go", "defer", "select",
// Bash keywords
"if", "then", "else", "elif", "fi", "case", "esac", "for", "while",
"until", "do", "done", "function",
// C# keywords
"namespace", "using", "class", "interface", "public", "private",
"protected", "static", "void", "new", "override"};
for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
if (strcmp(word, keywords[i]) == 0) {
return 1;
} }
return 0; }
return 0;
} }
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) {
if ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') || (*ptr == '_')) {
while ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') || (*ptr >= '0' && *ptr <= '9') || (*ptr == '_')) {
buffer[index++] = *ptr++;
}
buffer[index] = 0;
if (is_keyword(buffer)) { while (*ptr) {
printf(FG_BLUE "%s" RESET, buffer); if ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') ||
} else { (*ptr == '_')) {
printf("%s", buffer); while ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') ||
} (*ptr >= '0' && *ptr <= '9') || (*ptr == '_')) {
index = 0; buffer[index++] = *ptr++;
} else if (*ptr >= '0' && *ptr <= '9') { }
while (*ptr >= '0' && *ptr <= '9') { buffer[index] = 0;
buffer[index++] = *ptr++;
} if (is_keyword(buffer)) {
buffer[index] = 0; printf(FG_BLUE "%s" RESET, buffer);
printf(FG_CYAN "%s" RESET, buffer); } else {
index = 0; printf("%s", buffer);
} else { }
putchar(*ptr); index = 0;
ptr++; } else if (*ptr >= '0' && *ptr <= '9') {
} while (*ptr >= '0' && *ptr <= '9') {
buffer[index++] = *ptr++;
}
buffer[index] = 0;
printf(FG_CYAN "%s" RESET, buffer);
index = 0;
} else {
putchar(*ptr);
ptr++;
} }
}
} }
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 inside_code = false;
while (*ptr) { while (*ptr) {
if (*ptr == '`' && *(ptr + 1) != '`') { if (*ptr == '`' && *(ptr + 1) != '`') {
inside_code = !inside_code; inside_code = !inside_code;
if (inside_code) { if (inside_code) {
printf(FG_YELLOW); printf(FG_YELLOW);
} else { } else {
printf(RESET); printf(RESET);
} }
ptr++; ptr++;
continue; continue;
}else if(!strncmp(ptr, "```", 3)) { } else if (!strncmp(ptr, "```", 3)) {
inside_code = !inside_code; inside_code = !inside_code;
if(inside_code){ if (inside_code) {
ptr = strstr(ptr, "\n") + 1; ptr = strstr(ptr, "\n") + 1;
}else{ } else {
ptr+=3; ptr += 3;
} }
if(*ptr == '\0'){ if (*ptr == '\0') {
break; break;
} }
}
if (inside_code) {
char code_buffer[1024*1024] = {0};;
size_t index = 0;
while (*ptr && *ptr != '`') {
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++;
while (*ptr && *ptr != '*') {
putchar(*ptr++);
}
if (*ptr == '*') ptr++;
printf(RESET);
} else if (strncmp(ptr, "### ", 4) == 0) {
printf(BOLD FG_YELLOW);
ptr += 4;
while (*ptr && *ptr != '\n') {
putchar(*ptr++);
}
printf(RESET "\n");
} else if (strncmp(ptr, "## ", 3) == 0) {
printf(BOLD FG_YELLOW);
ptr += 3;
while (*ptr && *ptr != '\n') {
putchar(*ptr++);
}
printf(RESET "\n");
} else if (strncmp(ptr, "# ", 2) == 0) {
printf(BOLD FG_YELLOW);
ptr += 2;
while (*ptr && *ptr != '\n') {
putchar(*ptr++);
}
printf(RESET "\n");
} else {
putchar(*ptr);
ptr++;
}
}
} }
if (inside_code) {
char code_buffer[1024 * 1024] = {0};
;
size_t index = 0;
while (*ptr && *ptr != '`') {
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++;
while (*ptr && *ptr != '*') {
putchar(*ptr++);
}
if (*ptr == '*')
ptr++;
printf(RESET);
} else if (strncmp(ptr, "### ", 4) == 0) {
printf(BOLD FG_YELLOW);
ptr += 4;
while (*ptr && *ptr != '\n') {
putchar(*ptr++);
}
printf(RESET "\n");
} else if (strncmp(ptr, "## ", 3) == 0) {
printf(BOLD FG_YELLOW);
ptr += 3;
while (*ptr && *ptr != '\n') {
putchar(*ptr++);
}
printf(RESET "\n");
} else if (strncmp(ptr, "# ", 2) == 0) {
printf(BOLD FG_YELLOW);
ptr += 2;
while (*ptr && *ptr != '\n') {
putchar(*ptr++);
}
printf(RESET "\n");
} else {
putchar(*ptr);
ptr++;
}
}
}
} }

View File

@ -1,90 +1,106 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This code manages a collection of messages using JSON objects. It provides functions to retrieve all messages as a JSON array, add a new message with a specified role and content, and free the allocated resources. // This code manages a collection of messages using JSON objects. It provides
// functions to retrieve all messages as a JSON array, add a new message with a
// specified role and content, and free the allocated resources.
// Uses the external library <json-c/json.h> for JSON manipulation // Uses the external library <json-c/json.h> for JSON manipulation
// MIT License // 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: // Permission is hereby granted, free of charge, to any person obtaining a copy
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // of this software and associated documentation files (the "Software"), to deal
// 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. // 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.
#ifndef R_MESSAGES_H #ifndef R_MESSAGES_H
#define R_MESSAGES_H #define R_MESSAGES_H
#include <string.h>
#include "tools.h"
#include "json-c/json.h" #include "json-c/json.h"
#include "tools.h"
#include <string.h>
struct json_object *message_array = NULL; struct json_object *message_array = NULL;
struct json_object *message_list() { struct json_object *message_list() {
if (!message_array) { if (!message_array) {
message_array = json_object_new_array(); message_array = json_object_new_array();
} }
return message_array; return message_array;
} }
bool messages_remove_last() { bool messages_remove_last() {
struct json_object *messages = message_list(); struct json_object *messages = message_list();
int size = json_object_array_length(messages); int size = json_object_array_length(messages);
if (size) { if (size) {
json_object_array_del_idx(messages, size - 1, 1); json_object_array_del_idx(messages, size - 1, 1);
return true; return true;
} }
return false; return false;
} }
void messages_remove(){ void messages_remove() {
while(messages_remove_last()) while (messages_remove_last())
continue; continue;
} }
struct json_object *message_add_tool_call(struct json_object *message) { struct json_object *message_add_tool_call(struct json_object *message) {
struct json_object *messages = message_list(); struct json_object *messages = message_list();
json_object_array_add(messages, message); json_object_array_add(messages, message);
return message; return message;
} }
struct json_object *message_add_tool_result(const char *tool_call_id, const char *tool_result) { struct json_object *message_add_tool_result(const char *tool_call_id,
struct json_object *messages = message_list(); const char *tool_result) {
struct json_object *message = json_object_new_object(); struct json_object *messages = message_list();
struct json_object *message = json_object_new_object();
json_object_object_add(message, "tool_call_id", json_object_new_string(tool_call_id)); json_object_object_add(message, "tool_call_id",
json_object_object_add(message, "tool_result", json_object_new_string(tool_result)); json_object_new_string(tool_call_id));
json_object_object_add(message, "tool_result",
json_object_new_string(tool_result));
json_object_array_add(messages, message); json_object_array_add(messages, message);
return message; return message;
} }
void message_add_object(json_object *message) { void message_add_object(json_object *message) {
struct json_object *messages = message_list(); struct json_object *messages = message_list();
json_object_array_add(messages, message); json_object_array_add(messages, message);
} }
struct json_object *message_add(const char *role, const char *content) { struct json_object *message_add(const char *role, const char *content) {
struct json_object *messages = message_list(); struct json_object *messages = message_list();
struct json_object *message = json_object_new_object(); struct json_object *message = json_object_new_object();
json_object_object_add(message, "role", json_object_new_string(role)); json_object_object_add(message, "role", json_object_new_string(role));
json_object_object_add(message, "content", json_object_new_string(content)); json_object_object_add(message, "content", json_object_new_string(content));
if (!strcmp(role, "user")) { if (!strcmp(role, "user")) {
json_object_object_add(message, "tools", tools_descriptions()); json_object_object_add(message, "tools", tools_descriptions());
} }
json_object_array_add(messages, message); json_object_array_add(messages, message);
return message; return message;
} }
char *message_json() { char *message_json() {
return (char *)json_object_to_json_string_ext(message_list(), JSON_C_TO_STRING_PRETTY); return (char *)json_object_to_json_string_ext(message_list(),
JSON_C_TO_STRING_PRETTY);
} }
void message_free() { void message_free() {
if (message_array) { if (message_array) {
json_object_put(message_array); json_object_put(message_array);
message_array = NULL; message_array = NULL;
} }
} }
#endif #endif

179
openai.h
View File

@ -1,8 +1,11 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This code interacts with OpenAI's API to perform various tasks such as fetching models, sending chat messages, and processing responses. // This code interacts with OpenAI's API to perform various tasks such as
// fetching models, sending chat messages, and processing responses.
// Uncommon imports include "http.h", "chat.h", and "http_curl.h". These may be internal or external libraries providing HTTP and JSON communication capabilities required to interact with APIs. // Uncommon imports include "http.h", "chat.h", and "http_curl.h". These may be
// internal or external libraries providing HTTP and JSON communication
// capabilities required to interact with APIs.
// MIT License // MIT License
// //
@ -15,8 +18,8 @@
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in all // The above copyright notice and this permission notice shall be included in
// copies or substantial portions of the Software. // all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -26,109 +29,113 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
#ifndef R_OPENAI_H #ifndef R_OPENAI_H
#define R_OPENAI_H #define R_OPENAI_H
#include "chat.h" #include "chat.h"
#include "http_curl.h" #include "http_curl.h"
#include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
char* openai_fetch_models() { char *openai_fetch_models() {
const char* api_url = "https://api.openai.com/v1/models"; const char *api_url = "https://api.openai.com/v1/models";
return curl_get(api_url); return curl_get(api_url);
} }
bool openai_system(char* message_content) { bool openai_system(char *message_content) {
chat_json("system", message_content); chat_json("system", message_content);
return true; return true;
} }
struct json_object* openai_process_chat_message(const char* api_url, const char* json_data) { struct json_object *openai_process_chat_message(const char *api_url,
char* response = curl_post(api_url, json_data); const char *json_data) {
struct json_object* parsed_json = json_tokener_parse(response); char *response = curl_post(api_url, json_data);
if (!parsed_json) { struct json_object *parsed_json = json_tokener_parse(response);
fprintf(stderr, "Failed to parse JSON.\n%s\n", response); if (!parsed_json) {
return NULL; fprintf(stderr, "Failed to parse JSON.\n%s\n", response);
} return NULL;
struct json_object *error_object; }
if (json_object_object_get_ex(parsed_json, "error", &error_object)) { struct json_object *error_object;
if (json_object_object_get_ex(parsed_json, "error", &error_object)) {
char *all_messages = (char *)json_object_to_json_string(message_array); char *all_messages = (char *)json_object_to_json_string(message_array);
fprintf(stderr, "Messages: ");
fwrite(all_messages, strlen(all_messages), 1, stderr);
fprintf(stderr, "\n");
free(all_messages);
fprintf(stderr, "Messages: "); fprintf(stderr, "%s\n", json_object_to_json_string(parsed_json));
fwrite(all_messages, strlen(all_messages), 1, stderr);
fprintf(stderr, "\n");
free(all_messages);
fprintf(stderr,"%s\n",json_object_to_json_string(parsed_json));
json_object_put(parsed_json);
messages_remove_last();
messages_remove_last(); json_object_put(parsed_json);
messages_remove_last();
return NULL; messages_remove_last();
}
struct json_object* choices_array; return NULL;
if (!json_object_object_get_ex(parsed_json, "choices", &choices_array)) { }
fprintf(stderr, "Failed to get 'choices' array.\n%s\n", response);
json_object_put(parsed_json); struct json_object *choices_array;
return NULL; if (!json_object_object_get_ex(parsed_json, "choices", &choices_array)) {
} fprintf(stderr, "Failed to get 'choices' array.\n%s\n", response);
struct json_object* first_choice = json_object_array_get_idx(choices_array, 0); json_object_put(parsed_json);
if (!first_choice) { return NULL;
fprintf(stderr, "Failed to get the first element of 'choices'.\n"); }
json_object_put(parsed_json); struct json_object *first_choice =
return NULL; json_object_array_get_idx(choices_array, 0);
} if (!first_choice) {
struct json_object* message_object; fprintf(stderr, "Failed to get the first element of 'choices'.\n");
if (!json_object_object_get_ex(first_choice, "message", &message_object)) { json_object_put(parsed_json);
fprintf(stderr, "Failed to get 'message' object.\n"); return NULL;
json_object_put(parsed_json); }
return NULL; struct json_object *message_object;
} if (!json_object_object_get_ex(first_choice, "message", &message_object)) {
return message_object; fprintf(stderr, "Failed to get 'message' object.\n");
json_object_put(parsed_json);
return NULL;
}
return message_object;
} }
char* openai_chat(const char* user_role, const char* message_content) { char *openai_chat(const char *user_role, const char *message_content) {
if(message_content == NULL || *message_content == '\0' || *message_content == '\n') { if (message_content == NULL || *message_content == '\0' ||
return NULL; *message_content == '\n') {
} return NULL;
}
const char* api_url = "https://api.openai.com/v1/chat/completions";
char* json_data = chat_json(user_role, message_content); const char *api_url = "https://api.openai.com/v1/chat/completions";
char *json_data = chat_json(user_role, message_content);
struct json_object* message_object = openai_process_chat_message(api_url, json_data);
message_add_object(message_object); struct json_object *message_object =
if (message_object == NULL) { openai_process_chat_message(api_url, json_data);
printf("ERROR + NULL IS SUCCESS\n"); message_add_object(message_object);
return NULL; if (message_object == NULL) {
} printf("ERROR + NULL IS SUCCESS\n");
struct json_object* tool_calls; return NULL;
json_object_object_get_ex(message_object, "tool_calls", &tool_calls); }
if (tool_calls) { 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); // message_add_tool_call(message_object);
struct json_object* tool_call_results = tools_execute(tool_calls); struct json_object *tool_call_results = tools_execute(tool_calls);
int results_count = json_object_array_length(tool_call_results); int results_count = json_object_array_length(tool_call_results);
for (int i = 0; i < results_count; i++) { for (int i = 0; i < results_count; i++) {
struct json_object* tool_call_result = json_object_array_get_idx(tool_call_results, i); struct json_object *tool_call_result =
message_add_tool_call(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);
message_object = openai_process_chat_message(api_url, tool_calls_result_str);
if (message_object == NULL) {
return NULL;
}
message_add_object(message_object);
//message_add_tool_call(message_object);
} }
const char* content_str = json_object_get_string(json_object_object_get(message_object, "content")); char *tool_calls_result_str = chat_json(NULL, NULL);
return strdup(content_str); message_object =
openai_process_chat_message(api_url, tool_calls_result_str);
if (message_object == NULL) {
return NULL;
}
message_add_object(message_object);
// message_add_tool_call(message_object);
}
const char *content_str =
json_object_get_string(json_object_object_get(message_object, "content"));
return strdup(content_str);
} }
#endif #endif

View File

@ -1,58 +1,62 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This source code initializes a Python interpreter within a plugin, executes a provided Python script with some basic imports, and finalizes the Python environment when done. // This source code initializes a Python interpreter within a plugin, executes a
// provided Python script with some basic imports, and finalizes the Python
// environment when done.
// This code does not use any non-standard imports or includes aside from Python.h and structmember.h which are part of Python's C API. // This code does not use any non-standard imports or includes aside from
// Python.h and structmember.h which are part of Python's C API.
// MIT License // MIT License
#include <Python.h> #include <Python.h>
#include <structmember.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <structmember.h>
bool plugin_initialized = false; bool plugin_initialized = false;
bool plugin_construct() { bool plugin_construct() {
if (plugin_initialized) return true; if (plugin_initialized)
Py_Initialize();
if (!Py_IsInitialized()) {
fprintf(stderr, "Failed to initialize the Python interpreter\n");
return false;
}
plugin_initialized = true;
return true; return true;
Py_Initialize();
if (!Py_IsInitialized()) {
fprintf(stderr, "Failed to initialize the Python interpreter\n");
return false;
}
plugin_initialized = true;
return true;
} }
void plugin_run(char *src) { void plugin_run(char *src) {
plugin_construct(); plugin_construct();
/*const char *basics = /*const char *basics =
"import sys\n" "import sys\n"
"import os\n" "import os\n"
"from os import *\n" "from os import *\n"
"import math\n" "import math\n"
"import pathlib\n" "import pathlib\n"
"from pathlib import Path\n" "from pathlib import Path\n"
"import re\n" "import re\n"
"import subprocess\n" "import subprocess\n"
"from subprocess import *\n" "from subprocess import *\n"
"import time\n" "import time\n"
"from datetime import datetime\n" "from datetime import datetime\n"
"%s"; "%s";
*/ */
const char *basics = "\n\n"; const char *basics = "\n\n";
size_t length = strlen(basics) + strlen(src); size_t length = strlen(basics) + strlen(src);
char *script = malloc(length + 1); char *script = malloc(length + 1);
sprintf(script, basics, src); sprintf(script, basics, src);
script[length] = '\0'; script[length] = '\0';
PyRun_SimpleString(script); PyRun_SimpleString(script);
free(script); free(script);
} }
void plugin_destruct() { void plugin_destruct() {
if (plugin_initialized) Py_Finalize(); if (plugin_initialized)
Py_Finalize();
} }

36
r.h
View File

@ -1,38 +1,34 @@
#ifndef R_H #ifndef R_H
#define R_H #define R_H
#include "auth.h"
#include "malloc.h" #include "malloc.h"
#include "utils.h"
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include "utils.h"
#include "auth.h"
bool is_verbose = false; bool is_verbose = false;
char * _model = NULL; char *_model = NULL;
#define DB_FILE "~/.r.db" #define DB_FILE "~/.r.db"
static int prompt_max_tokens = 10000; static int prompt_max_tokens = 10000;
#define PROMPT_TEMPERATURE 0.1 #define PROMPT_TEMPERATURE 0.1
void set_prompt_model(const char *model) { void set_prompt_model(const char *model) {
if(_model != NULL) { if (_model != NULL) {
free(_model); free(_model);
} }
_model = strdup(model); _model = strdup(model);
} }
const char * get_prompt_model() { const char *get_prompt_model() {
if(auth_type != AUTH_TYPE_API_KEY) { if (auth_type != AUTH_TYPE_API_KEY) {
if(_model == NULL) { if (_model == NULL) {
_model = strdup("gpt-3.5-turbo"); _model = strdup("gpt-3.5-turbo");
}
} else if(_model == NULL) {
_model = strdup("gpt-4o-mini");
} }
return _model; } else if (_model == NULL) {
_model = strdup("gpt-4o-mini");
}
return _model;
} }
#endif
#endif

113
rpylib.c
View File

@ -1,28 +1,29 @@
/* Written by retoor@molodetz.nl */ /* Written by retoor@molodetz.nl */
/* /*
This C extension for Python provides a simple API for communication with an OpenAI service. This C extension for Python provides a simple API for communication with an
It includes functions to return a "Hello World" string, conduct a chat session through OpenAI, and reset the message history. OpenAI service. It includes functions to return a "Hello World" string, conduct
a chat session through OpenAI, and reset the message history.
*/ */
/* /*
Summary of used imports: Summary of used imports:
- <Python.h>: Includes necessary Python headers to create a C extension. - <Python.h>: Includes necessary Python headers to create a C extension.
- "openai.h": Assumes an external library for OpenAI interaction. - "openai.h": Assumes an external library for OpenAI interaction.
*/ */
/* /*
MIT License MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -34,72 +35,66 @@ SOFTWARE.
*/ */
#define PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "openai.h"
#include "auth.h" #include "auth.h"
#include "openai.h"
#include <Python.h>
static PyObject* rpylib_reset(PyObject *self, PyObject *args) { static PyObject *rpylib_reset(PyObject *self, PyObject *args) {
return PyUnicode_FromString("True"); return PyUnicode_FromString("True");
} }
static PyObject* rpylib_chat(PyObject *self, PyObject *args) { static PyObject *rpylib_chat(PyObject *self, PyObject *args) {
const char *role, *message; const char *role, *message;
printf("That goes alright! 1\n");
printf("That goes alright! 1\n"); if (!PyArg_ParseTuple(args, "ss", &role, &message)) {
if (!PyArg_ParseTuple(args, "ss", &role, &message)) { return NULL;
return NULL; }
} printf("That goes alright! 2\n");
printf("That goes alright! 2\n"); char *result = openai_chat(role, message);
char *result = openai_chat(role, message); PyObject *py_result = PyUnicode_FromString(result);
PyObject *py_result = PyUnicode_FromString(result); free(result);
free(result); return py_result;
return py_result;
} }
static PyObject* rpylib_prompt(PyObject *self, PyObject *args) { static PyObject *rpylib_prompt(PyObject *self, PyObject *args) {
const char *role = "user"; const char *role = "user";
const char *message; const char *message;
if (!PyArg_ParseTuple(args, "s", &message)) { if (!PyArg_ParseTuple(args, "s", &message)) {
return NULL; return NULL;
} }
char *result = openai_chat(role, message); char *result = openai_chat(role, message);
PyObject *py_result = PyUnicode_FromString(result); PyObject *py_result = PyUnicode_FromString(result);
free(result); free(result);
return py_result; return py_result;
} }
static PyObject* rpylib_system(PyObject *self, PyObject *args) { static PyObject *rpylib_system(PyObject *self, PyObject *args) {
const char *role = "system"; const char *role = "system";
const char *message; const char *message;
if (!PyArg_ParseTuple(args, "s", &message)) { if (!PyArg_ParseTuple(args, "s", &message)) {
return NULL; return NULL;
} }
char *result = openai_chat(role, message); char *result = openai_chat(role, message);
PyObject *py_result = PyUnicode_FromString(result); PyObject *py_result = PyUnicode_FromString(result);
free(result); free(result);
return py_result; return py_result;
} }
static PyMethodDef MyModuleMethods[] = { static PyMethodDef MyModuleMethods[] = {
{"chat", rpylib_chat, METH_VARARGS, "Chat with OpenAI."}, {"chat", rpylib_chat, METH_VARARGS, "Chat with OpenAI."},
//{"prompt", rpylib_prompt, METH_VARARGS, "Prompt to OpenAI."}, //{"prompt", rpylib_prompt, METH_VARARGS, "Prompt to OpenAI."},
//{"system", rpylib_system, METH_VARARGS, "Add system message."}, //{"system", rpylib_system, METH_VARARGS, "Add system message."},
{"reset", rpylib_reset, METH_NOARGS, "Reset message history."}, {"reset", rpylib_reset, METH_NOARGS, "Reset message history."},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}};
};
static struct PyModuleDef rpylib = { static struct PyModuleDef rpylib = {
PyModuleDef_HEAD_INIT, PyModuleDef_HEAD_INIT, "rpylib",
"rpylib", "R - the power of R in Python, made by retoor.", -1, MyModuleMethods};
"R - the power of R in Python, made by retoor.",
-1,
MyModuleMethods
};
PyMODINIT_FUNC PyInit_rpylib(void) { PyMODINIT_FUNC PyInit_rpylib(void) {
auth_init(); auth_init();
printf("Init\n"); printf("Init\n");
void * res = PyModule_Create(&rpylib); void *res = PyModule_Create(&rpylib);
printf("GLOB\n"); printf("GLOB\n");
return res; return res;
} }

BIN
rpylib.so

Binary file not shown.

2199
tools.h

File diff suppressed because it is too large Load Diff

129
url.h
View File

@ -1,85 +1,102 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This code defines a URL parser in C that extracts components such as the scheme, hostname, port, path, and query from a given URL. // This code defines a URL parser in C that extracts components such as the
// scheme, hostname, port, path, and query from a given URL.
// Includes: // Includes:
// - <stdio.h> for standard I/O operations // - <stdio.h> for standard I/O operations
// - <string.h> for string manipulation functions // - <string.h> for string manipulation functions
// - <stdlib.h> for memory allocation and management // - <stdlib.h> for memory allocation and management
// MIT License // 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. // 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.
#ifndef R_URL_H #ifndef R_URL_H
#define R_URL_H #define R_URL_H
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
typedef struct { typedef struct {
char scheme[16]; char scheme[16];
char hostname[256]; char hostname[256];
char port[8]; char port[8];
char path[512]; char path[512];
char query[512]; char query[512];
} url_t; } url_t;
int parse_url(const char *url, url_t *parsed_url) { int parse_url(const char *url, url_t *parsed_url) {
memset(parsed_url, 0, sizeof(url_t)); memset(parsed_url, 0, sizeof(url_t));
const char *scheme_end = strstr(url, "://"); const char *scheme_end = strstr(url, "://");
if (!scheme_end) { if (!scheme_end) {
return -1; return -1;
}
strncpy(parsed_url->scheme, url, scheme_end - url);
parsed_url->scheme[scheme_end - url] = '\0';
const char *hostname_start = scheme_end + 3;
const char *port_start = strchr(hostname_start, ':');
const char *path_start = strchr(hostname_start, '/');
const char *query_start = strchr(hostname_start, '?');
if (port_start && (!path_start || port_start < path_start)) {
size_t hostname_length = port_start - hostname_start;
if (hostname_length >= sizeof(parsed_url->hostname)) {
fprintf(stderr, "Hostname is too long\n");
return -1;
} }
strncpy(parsed_url->hostname, hostname_start, hostname_length);
parsed_url->hostname[hostname_length] = '\0';
strncpy(parsed_url->scheme, url, scheme_end - url); size_t port_length = query_start ? (size_t)(query_start - port_start - 1)
parsed_url->scheme[scheme_end - url] = '\0'; : strlen(port_start + 1);
if (port_length >= sizeof(parsed_url->port)) {
const char *hostname_start = scheme_end + 3; fprintf(stderr, "Port value is too long\n");
const char *port_start = strchr(hostname_start, ':'); return -1;
const char *path_start = strchr(hostname_start, '/');
const char *query_start = strchr(hostname_start, '?');
if (port_start && (!path_start || port_start < path_start)) {
size_t hostname_length = port_start - hostname_start;
if (hostname_length >= sizeof(parsed_url->hostname)) {
fprintf(stderr, "Hostname is too long\n");
return -1;
}
strncpy(parsed_url->hostname, hostname_start, hostname_length);
parsed_url->hostname[hostname_length] = '\0';
size_t port_length = query_start ? (size_t)(query_start - port_start - 1) : strlen(port_start + 1);
if (port_length >= sizeof(parsed_url->port)) {
fprintf(stderr, "Port value is too long\n");
return -1;
}
strncpy(parsed_url->port, port_start + 1, port_length);
parsed_url->port[port_length] = '\0';
} else {
size_t hostname_length = path_start ? (size_t)(path_start - hostname_start) :
(query_start ? (size_t)(query_start - hostname_start) : strlen(hostname_start));
if (hostname_length >= sizeof(parsed_url->hostname)) {
fprintf(stderr, "Hostname is too long\n");
return -1;
}
strncpy(parsed_url->hostname, hostname_start, hostname_length);
parsed_url->hostname[hostname_length] = '\0';
} }
strncpy(parsed_url->port, port_start + 1, port_length);
if (path_start) { parsed_url->port[port_length] = '\0';
if (query_start) { } else {
strncpy(parsed_url->path, path_start, query_start - path_start); size_t hostname_length =
parsed_url->path[query_start - path_start] = '\0'; path_start ? (size_t)(path_start - hostname_start)
} else { : (query_start ? (size_t)(query_start - hostname_start)
strcpy(parsed_url->path, path_start); : strlen(hostname_start));
} if (hostname_length >= sizeof(parsed_url->hostname)) {
fprintf(stderr, "Hostname is too long\n");
return -1;
} }
strncpy(parsed_url->hostname, hostname_start, hostname_length);
parsed_url->hostname[hostname_length] = '\0';
}
if (path_start) {
if (query_start) { if (query_start) {
strcpy(parsed_url->query, query_start + 1); strncpy(parsed_url->path, path_start, query_start - path_start);
parsed_url->path[query_start - path_start] = '\0';
} else {
strcpy(parsed_url->path, path_start);
} }
}
return 0; if (query_start) {
strcpy(parsed_url->query, query_start + 1);
}
return 0;
} }
#endif #endif

104
utils.h
View File

@ -1,69 +1,77 @@
// Written by retoor@molodetz.nl // Written by retoor@molodetz.nl
// This header file contains utility functions for manipulating file system paths, focusing primarily on expanding paths starting with '~' to the home directory. // This header file contains utility functions for manipulating file system
// paths, focusing primarily on expanding paths starting with '~' to the home
// directory.
// This code uses standard libraries: stdio.h, stdlib.h, and string.h, and conditionally includes the posix libraries pwd.h and unistd.h when expanding the home directory manually. // This code uses standard libraries: stdio.h, stdlib.h, and string.h, and
// conditionally includes the posix libraries pwd.h and unistd.h when expanding
// the home directory manually.
// MIT License // MIT License
// //
// Permission is granted to use, copy, modify, merge, distribute, sublicense, and/or sell copies of the Software. // Permission is granted to use, copy, modify, merge, distribute, sublicense,
// The license includes conditions about providing a copy of the license and the limitation of liability and warranty. // and/or sell copies of the Software. The license includes conditions about
// providing a copy of the license and the limitation of liability and warranty.
#ifndef UTILS_H #ifndef UTILS_H
#define UTILS_H #define UTILS_H
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
char* expand_home_directory(const char* path) { char *expand_home_directory(const char *path) {
if (path == NULL) return NULL; if (path == NULL)
return NULL;
if (path[0] == '~' && path[1] == '/') { if (path[0] == '~' && path[1] == '/') {
const char* home_dir = getenv("HOME"); const char *home_dir = getenv("HOME");
if (home_dir == NULL) { if (home_dir == NULL) {
#include <pwd.h> #include <pwd.h>
#include <unistd.h> #include <unistd.h>
struct passwd* pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
if (pw == NULL) return NULL; if (pw == NULL)
home_dir = pw->pw_dir; return NULL;
} home_dir = pw->pw_dir;
size_t home_len = strlen(home_dir);
size_t path_len = strlen(path) - 1;
char* expanded_path = malloc(home_len + path_len + 1);
if (expanded_path == NULL) return NULL;
strcpy(expanded_path, home_dir);
strcat(expanded_path, path + 1);
return expanded_path;
} else {
return strdup(path);
} }
size_t home_len = strlen(home_dir);
size_t path_len = strlen(path) - 1;
char *expanded_path = malloc(home_len + path_len + 1);
if (expanded_path == NULL)
return NULL;
strcpy(expanded_path, home_dir);
strcat(expanded_path, path + 1);
return expanded_path;
} else {
return strdup(path);
}
} }
char * read_file(const char * path) { char *read_file(const char *path) {
char * expanded_path = expand_home_directory(path); char *expanded_path = expand_home_directory(path);
FILE *file = fopen(expanded_path, "r"); FILE *file = fopen(expanded_path, "r");
free(expanded_path); free(expanded_path);
if (file == NULL) { if (file == NULL) {
return NULL; return NULL;
} }
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
long size = ftell(file); long size = ftell(file);
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
char *buffer = (char *)malloc(size + 1); char *buffer = (char *)malloc(size + 1);
size_t read = fread(buffer, 1, size, file); size_t read = fread(buffer, 1, size, file);
if (read == 0) { if (read == 0) {
free(buffer); free(buffer);
return NULL; return NULL;
} }
fclose(file); fclose(file);
buffer[read] = '\0'; buffer[read] = '\0';
return buffer; return buffer;
} }
#endif #endif