Formatting.
This commit is contained in:
parent
1e62665d43
commit
bff6e758bc
64
auth.h
64
auth.h
@ -1,69 +1,65 @@
|
||||
// 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
|
||||
|
||||
#ifndef R_AUTH_H
|
||||
#define R_AUTH_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
enum AUTH_TYPE {
|
||||
AUTH_TYPE_NONE,
|
||||
AUTH_TYPE_API_KEY,
|
||||
AUTH_TYPE_FREE
|
||||
};
|
||||
enum AUTH_TYPE { AUTH_TYPE_NONE, AUTH_TYPE_API_KEY, AUTH_TYPE_FREE };
|
||||
|
||||
int auth_type = AUTH_TYPE_NONE;
|
||||
|
||||
void auth_free(){
|
||||
auth_type = AUTH_TYPE_FREE;
|
||||
}
|
||||
void auth_free() { auth_type = AUTH_TYPE_FREE; }
|
||||
|
||||
void auth_init() {
|
||||
|
||||
char *api_key = NULL;
|
||||
if(auth_type != AUTH_TYPE_FREE) {
|
||||
|
||||
|
||||
char *api_key = NULL;
|
||||
if (auth_type != AUTH_TYPE_FREE) {
|
||||
|
||||
api_key = getenv("R_KEY");
|
||||
if (api_key) {
|
||||
auth_type = AUTH_TYPE_API_KEY;
|
||||
return;
|
||||
auth_type = AUTH_TYPE_API_KEY;
|
||||
return;
|
||||
}
|
||||
api_key = getenv("OPENAI_API_KEY");
|
||||
if (api_key) {
|
||||
auth_type = AUTH_TYPE_API_KEY;
|
||||
return;
|
||||
auth_type = AUTH_TYPE_API_KEY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
auth_type = AUTH_TYPE_FREE;
|
||||
return;
|
||||
}
|
||||
auth_type = AUTH_TYPE_FREE;
|
||||
return;
|
||||
}
|
||||
|
||||
const char *resolve_api_key() {
|
||||
static char *api_key = NULL;
|
||||
if(auth_type != AUTH_TYPE_FREE) {
|
||||
|
||||
static char *api_key = NULL;
|
||||
if (auth_type != AUTH_TYPE_FREE) {
|
||||
|
||||
api_key = getenv("R_KEY");
|
||||
if (api_key) {
|
||||
auth_type = AUTH_TYPE_API_KEY;
|
||||
return api_key;
|
||||
auth_type = AUTH_TYPE_API_KEY;
|
||||
return api_key;
|
||||
}
|
||||
api_key = getenv("OPENAI_API_KEY");
|
||||
if (api_key) {
|
||||
auth_type = AUTH_TYPE_API_KEY;
|
||||
return api_key;
|
||||
auth_type = AUTH_TYPE_API_KEY;
|
||||
return api_key;
|
||||
}
|
||||
}
|
||||
auth_type = AUTH_TYPE_FREE;
|
||||
api_key = "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";
|
||||
return api_key;
|
||||
}
|
||||
auth_type = AUTH_TYPE_FREE;
|
||||
api_key = "sk-proj-d798HLfWYBeB9HT_o7isaY0s88631IaYhhOR5IVAd4D_fF-"
|
||||
"SQ5z46BCr8iDi1ang1rUmlagw55T3BlbkFJ6IOsqhAxNN9Zt6ERDBnv2p2HCc2fDgc"
|
||||
"5DsNhPxdOzYb009J6CNd4wILPsFGEoUdWo4QrZ1eOkA";
|
||||
return api_key;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
20
browse.c
20
browse.c
@ -1,15 +1,15 @@
|
||||
#include "browse.h"
|
||||
|
||||
int main() {
|
||||
char *query = "example";
|
||||
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");
|
||||
}
|
||||
char *query = "example";
|
||||
char *result = get_news(query);
|
||||
|
||||
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;
|
||||
}
|
98
browse.h
98
browse.h
@ -1,63 +1,63 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "http_curl.h"
|
||||
#include <curl/curl.h>
|
||||
#include <json-c/json.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){
|
||||
return curl_easy_escape(NULL, s, 0);
|
||||
}
|
||||
char *web_search_news(char *q) {
|
||||
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){
|
||||
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);
|
||||
|
||||
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 *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);
|
||||
return ret;
|
||||
free(ret);
|
||||
return web_search_news(q);
|
||||
}
|
||||
json_object_put(json_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char * web_search(char * q){
|
||||
char * news = (char *)malloc(4096);
|
||||
news[0] = 0;
|
||||
char * q_encoded = url_encode(q);
|
||||
sprintf(news, "https://search.molodetz.nl/search?q=%s&format=json",q_encoded);
|
||||
free(q_encoded);
|
||||
char * ret = curl_get(news);
|
||||
free(news);
|
||||
json_object * json_ret = json_tokener_parse(ret);
|
||||
char *web_search(char *q) {
|
||||
char *news = (char *)malloc(4096);
|
||||
news[0] = 0;
|
||||
char *q_encoded = url_encode(q);
|
||||
sprintf(news, "https://search.molodetz.nl/search?q=%s&format=json",
|
||||
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(q);
|
||||
}
|
||||
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);
|
||||
return ret;
|
||||
free(ret);
|
||||
return web_search(q);
|
||||
}
|
||||
json_object_put(json_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char * web_search_engine(char * q){
|
||||
char * searx = malloc(4096);
|
||||
searx[0] = 0;
|
||||
sprintf(searx, "https://searx.molodetz.nl/search?q=%s&format=json", q);
|
||||
char * ret = curl_get(searx);
|
||||
free(searx);
|
||||
return ret;
|
||||
char *web_search_engine(char *q) {
|
||||
char *searx = malloc(4096);
|
||||
searx[0] = 0;
|
||||
sprintf(searx, "https://searx.molodetz.nl/search?q=%s&format=json", q);
|
||||
char *ret = curl_get(searx);
|
||||
free(searx);
|
||||
return ret;
|
||||
}
|
||||
|
50
chat.h
50
chat.h
@ -1,8 +1,8 @@
|
||||
// Written by retoor@molodetz.nl
|
||||
|
||||
// This code defines functionality for creating and managing JSON-based chat prompts
|
||||
// using a specific AI model configuration, providing easy integration with message handling
|
||||
// and HTTP communication for dynamic applications.
|
||||
// This code defines functionality for creating and managing JSON-based chat
|
||||
// prompts using a specific AI model configuration, providing easy integration
|
||||
// with message handling and HTTP communication for dynamic applications.
|
||||
|
||||
// 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
|
||||
// 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 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,
|
||||
@ -26,38 +26,42 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
|
||||
#ifndef R_PROMPT_H
|
||||
#define R_PROMPT_H
|
||||
|
||||
#include "tools.h"
|
||||
#include "auth.h"
|
||||
#include <json-c/json.h>
|
||||
#include "messages.h"
|
||||
#include "r.h"
|
||||
#include "tools.h"
|
||||
#include <json-c/json.h>
|
||||
static json_object *_prompt = NULL;
|
||||
|
||||
void chat_free() {
|
||||
if (_prompt == NULL) return;
|
||||
json_object_put(_prompt);
|
||||
_prompt = NULL;
|
||||
if (_prompt == NULL)
|
||||
return;
|
||||
json_object_put(_prompt);
|
||||
_prompt = NULL;
|
||||
}
|
||||
|
||||
char *chat_json(const char *role, const char *message) {
|
||||
chat_free();
|
||||
json_object *root_object = json_object_new_object();
|
||||
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());
|
||||
}
|
||||
chat_free();
|
||||
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, "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));
|
||||
if (role != NULL && message != NULL) {
|
||||
message_add(role, message);
|
||||
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
|
||||
|
79
db_utils.c
79
db_utils.c
@ -1,59 +1,60 @@
|
||||
#include <stdio.h>
|
||||
#include "db_utils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void db_initialize() {
|
||||
sqlite3 *db;
|
||||
char *err_msg = 0;
|
||||
int rc = sqlite3_open("database.db", &db);
|
||||
sqlite3 *db;
|
||||
char *err_msg = 0;
|
||||
int rc = sqlite3_open("database.db", &db);
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
return;
|
||||
}
|
||||
if (rc != SQLITE_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *sql = "CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT);";
|
||||
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
|
||||
const char *sql =
|
||||
"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) {
|
||||
sqlite3_free(err_msg);
|
||||
}
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_free(err_msg);
|
||||
}
|
||||
|
||||
sqlite3_close(db);
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
||||
void test_db_set() {
|
||||
json_object *result = db_set("test_key", "test_value");
|
||||
if (result) {
|
||||
printf("db_set: %s\n", json_object_get_string(result));
|
||||
json_object_put(result);
|
||||
} else {
|
||||
printf("db_set failed\n");
|
||||
}
|
||||
json_object *result = db_set("test_key", "test_value");
|
||||
if (result) {
|
||||
printf("db_set: %s\n", json_object_get_string(result));
|
||||
json_object_put(result);
|
||||
} else {
|
||||
printf("db_set failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void test_db_get() {
|
||||
json_object *result = db_get("test_key");
|
||||
if (result) {
|
||||
printf("db_get: %s\n", json_object_to_json_string(result));
|
||||
json_object_put(result);
|
||||
} else {
|
||||
printf("db_get failed\n");
|
||||
}
|
||||
json_object *result = db_get("test_key");
|
||||
if (result) {
|
||||
printf("db_get: %s\n", json_object_to_json_string(result));
|
||||
json_object_put(result);
|
||||
} else {
|
||||
printf("db_get failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void test_db_query() {
|
||||
json_object *result = db_query("SELECT * FROM kv_store");
|
||||
if (result) {
|
||||
printf("db_query: %s\n", json_object_to_json_string(result));
|
||||
json_object_put(result);
|
||||
} else {
|
||||
printf("db_query failed\n");
|
||||
}
|
||||
json_object *result = db_query("SELECT * FROM kv_store");
|
||||
if (result) {
|
||||
printf("db_query: %s\n", json_object_to_json_string(result));
|
||||
json_object_put(result);
|
||||
} else {
|
||||
printf("db_query failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
db_initialize();
|
||||
test_db_set();
|
||||
test_db_get();
|
||||
test_db_query();
|
||||
return 0;
|
||||
db_initialize();
|
||||
test_db_set();
|
||||
test_db_get();
|
||||
test_db_query();
|
||||
return 0;
|
||||
}
|
300
db_utils.h
300
db_utils.h
@ -2,178 +2,190 @@
|
||||
#define DB_UTILS_H
|
||||
|
||||
#include "r.h"
|
||||
#include <sqlite3.h>
|
||||
#include <json-c/json.h>
|
||||
#include "utils.h"
|
||||
#include <json-c/json.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
json_object *db_execute(const char *query);
|
||||
|
||||
|
||||
|
||||
json_object* db_execute(const char *query);
|
||||
|
||||
char * db_file_expanded(){
|
||||
char * expanded = expand_home_directory(DB_FILE);
|
||||
static char result[4096];
|
||||
result[0] = 0;
|
||||
strcpy(result, expanded);
|
||||
free(expanded);
|
||||
return result;
|
||||
char *db_file_expanded() {
|
||||
char *expanded = expand_home_directory(DB_FILE);
|
||||
static char result[4096];
|
||||
result[0] = 0;
|
||||
strcpy(result, expanded);
|
||||
free(expanded);
|
||||
return result;
|
||||
}
|
||||
|
||||
void db_initialize();
|
||||
json_object * db_set(const char *key, const char *value);
|
||||
json_object* db_get(const char *key);
|
||||
json_object* db_query(const char *query);
|
||||
|
||||
json_object *db_set(const char *key, const char *value);
|
||||
json_object *db_get(const char *key);
|
||||
json_object *db_query(const char *query);
|
||||
|
||||
void db_initialize() {
|
||||
sqlite3 *db;
|
||||
char *err_msg = 0;
|
||||
int rc = sqlite3_open(db_file_expanded(), &db);
|
||||
sqlite3 *db;
|
||||
char *err_msg = 0;
|
||||
int rc = sqlite3_open(db_file_expanded(), &db);
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
return;
|
||||
}
|
||||
if (rc != SQLITE_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *sql = "CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT);";
|
||||
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
|
||||
const char *sql =
|
||||
"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) {
|
||||
sqlite3_free(err_msg);
|
||||
}
|
||||
if (rc != SQLITE_OK) {
|
||||
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) {
|
||||
sqlite3 *db;
|
||||
char *err_msg = 0;
|
||||
int rc = sqlite3_open(db_file_expanded(), &db);
|
||||
if (rc != SQLITE_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
sqlite3_free(sql);
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_free(err_msg);
|
||||
sqlite3_close(db);
|
||||
return NULL;
|
||||
}
|
||||
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);
|
||||
sqlite3_free(sql);
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
sqlite3_free(err_msg);
|
||||
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) {
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *stmt;
|
||||
json_object *result = json_object_new_object();
|
||||
const char *value = NULL;
|
||||
json_object *db_get(const char *key) {
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *stmt;
|
||||
json_object *result = json_object_new_object();
|
||||
const char *value = NULL;
|
||||
|
||||
int rc = sqlite3_open(db_file_expanded(), &db);
|
||||
if (rc != SQLITE_OK) {
|
||||
return NULL;
|
||||
int rc = sqlite3_open(db_file_expanded(), &db);
|
||||
if (rc != SQLITE_OK) {
|
||||
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_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
value = (const char *)sqlite3_column_text(stmt, 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
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();
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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
|
||||
|
156
http_curl.h
156
http_curl.h
@ -1,8 +1,12 @@
|
||||
// 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
|
||||
// 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
|
||||
// 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.
|
||||
|
||||
// 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 HTTP_CURL
|
||||
#define HTTP_CURL
|
||||
|
||||
#include "auth.h"
|
||||
#include <curl/curl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <curl/curl.h>
|
||||
#include "auth.h"
|
||||
|
||||
struct ResponseBuffer {
|
||||
char *data;
|
||||
size_t size;
|
||||
char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
|
||||
size_t total_size = size * nmemb;
|
||||
struct ResponseBuffer *response = (struct ResponseBuffer *)userp;
|
||||
char *ptr = realloc(response->data, response->size + total_size + 1);
|
||||
if (ptr == NULL) {
|
||||
fprintf(stderr, "Failed to allocate memory for response\n");
|
||||
return 0;
|
||||
}
|
||||
response->data = ptr;
|
||||
memcpy(&(response->data[response->size]), contents, total_size);
|
||||
response->size += total_size;
|
||||
response->data[response->size] = '\0';
|
||||
return total_size;
|
||||
static size_t WriteCallback(void *contents, size_t size, size_t nmemb,
|
||||
void *userp) {
|
||||
size_t total_size = size * nmemb;
|
||||
struct ResponseBuffer *response = (struct ResponseBuffer *)userp;
|
||||
char *ptr = realloc(response->data, response->size + total_size + 1);
|
||||
if (ptr == NULL) {
|
||||
fprintf(stderr, "Failed to allocate memory for response\n");
|
||||
return 0;
|
||||
}
|
||||
response->data = ptr;
|
||||
memcpy(&(response->data[response->size]), contents, total_size);
|
||||
response->size += total_size;
|
||||
response->data[response->size] = '\0';
|
||||
return total_size;
|
||||
}
|
||||
|
||||
char *curl_post(const char *url, const char *data) {
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct ResponseBuffer response = {malloc(1), 0};
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct ResponseBuffer response = {malloc(1), 0};
|
||||
|
||||
if (!response.data) 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;
|
||||
}
|
||||
if (!response.data)
|
||||
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) {
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct ResponseBuffer response = {malloc(1), 0};
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct ResponseBuffer response = {malloc(1), 0};
|
||||
|
||||
if (!response.data) return NULL;
|
||||
if (!response.data)
|
||||
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_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);
|
||||
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_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));
|
||||
}
|
||||
return response.data;
|
||||
curl_slist_free_all(headers);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return response.data;
|
||||
}
|
||||
|
||||
#endif
|
228
indexer.h
228
indexer.h
@ -1,133 +1,157 @@
|
||||
#include <dirent.h>
|
||||
#include <json-c/json.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <json-c/json.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#define MAX_FILES 20000
|
||||
#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 size_t ext_count = sizeof(extensions) / sizeof(extensions[0]); // Updated count to reflect the new number of extensions
|
||||
|
||||
|
||||
static const char *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 {
|
||||
char name[MAX_PATH];
|
||||
char modification_date[20];
|
||||
char creation_date[20];
|
||||
char type[10];
|
||||
size_t size_bytes;
|
||||
char name[MAX_PATH];
|
||||
char modification_date[20];
|
||||
char creation_date[20];
|
||||
char type[10];
|
||||
size_t size_bytes;
|
||||
} FileInfo;
|
||||
|
||||
FileInfo file_list[MAX_FILES];
|
||||
size_t file_count = 0;
|
||||
|
||||
int is_valid_extension(const char *filename, const char *extensions[], size_t ext_count) {
|
||||
const char *dot = strrchr(filename, '.');
|
||||
if(!dot){
|
||||
dot = filename;
|
||||
}
|
||||
for (size_t i = 0; i < ext_count; i++) {
|
||||
if (strcmp(dot, extensions[i]) == 0) {
|
||||
return 1;
|
||||
}
|
||||
int is_valid_extension(const char *filename, const char *extensions[],
|
||||
size_t ext_count) {
|
||||
const char *dot = strrchr(filename, '.');
|
||||
if (!dot) {
|
||||
dot = filename;
|
||||
}
|
||||
for (size_t i = 0; i < ext_count; i++) {
|
||||
if (strcmp(dot, extensions[i]) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_ignored_directory(const char *dir_name) {
|
||||
const char *ignored_dirs[] = {"env", ".venv", "node_modules", "venv", "virtualenv"};
|
||||
for (size_t i = 0; i < sizeof(ignored_dirs) / sizeof(ignored_dirs[0]); i++) {
|
||||
if (strcmp(dir_name, ignored_dirs[i]) == 0) {
|
||||
return 1;
|
||||
}
|
||||
const char *ignored_dirs[] = {"env", ".venv", "node_modules", "venv",
|
||||
"virtualenv"};
|
||||
for (size_t i = 0; i < sizeof(ignored_dirs) / sizeof(ignored_dirs[0]); i++) {
|
||||
if (strcmp(dir_name, ignored_dirs[i]) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_file_info(const char *path) {
|
||||
struct stat file_stat;
|
||||
if (stat(path, &file_stat) == 0) {
|
||||
FileInfo info;
|
||||
strncpy(info.name, path, MAX_PATH - 1); // Copy with one less to leave space for null terminator
|
||||
info.name[MAX_PATH - 1] = '\0'; // Ensure null termination
|
||||
strftime(info.modification_date, sizeof(info.modification_date), "%Y-%m-%d %H:%M:%S", localtime(&file_stat.st_mtime));
|
||||
strftime(info.creation_date, sizeof(info.creation_date), "%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;
|
||||
}
|
||||
struct stat file_stat;
|
||||
if (stat(path, &file_stat) == 0) {
|
||||
FileInfo info;
|
||||
strncpy(info.name, path,
|
||||
MAX_PATH -
|
||||
1); // Copy with one less to leave space for null terminator
|
||||
info.name[MAX_PATH - 1] = '\0'; // Ensure null termination
|
||||
strftime(info.modification_date, sizeof(info.modification_date),
|
||||
"%Y-%m-%d %H:%M:%S", localtime(&file_stat.st_mtime));
|
||||
strftime(info.creation_date, sizeof(info.creation_date),
|
||||
"%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) {
|
||||
DIR *dir = opendir(dir_path);
|
||||
struct dirent *entry;
|
||||
if (dir == NULL) {
|
||||
perror("Failed to open directory");
|
||||
return NULL;
|
||||
}
|
||||
char *index_directory(const char *dir_path) {
|
||||
DIR *dir = opendir(dir_path);
|
||||
struct dirent *entry;
|
||||
if (dir == NULL) {
|
||||
perror("Failed to open directory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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));
|
||||
json_object *jarray = json_object_new_array();
|
||||
|
||||
// Read the file contents
|
||||
FILE *fp = fopen(file_list[file_count - 1].name, "r");
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
} 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));
|
||||
|
||||
char *result = strdup(json_object_to_json_string(jarray));
|
||||
json_object_put(jarray);
|
||||
return result;
|
||||
// Read the file contents
|
||||
FILE *fp = fopen(file_list[file_count - 1].name, "r");
|
||||
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;
|
||||
}
|
||||
|
@ -1,47 +1,50 @@
|
||||
// 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
|
||||
|
||||
|
||||
#include <regex.h>
|
||||
#include "http.h"
|
||||
#include "url.h"
|
||||
#include <regex.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void extract_urls(const char *input, char **urls, int *url_count) {
|
||||
const char *pattern = "https?://[^ ]+";
|
||||
regex_t regex;
|
||||
regcomp(®ex, pattern, REG_EXTENDED);
|
||||
regmatch_t match;
|
||||
const char *cursor = input;
|
||||
const char *pattern = "https?://[^ ]+";
|
||||
regex_t regex;
|
||||
regcomp(®ex, pattern, REG_EXTENDED);
|
||||
regmatch_t match;
|
||||
const char *cursor = input;
|
||||
|
||||
*url_count = 0;
|
||||
while (!regexec(®ex, cursor, 1, &match, 0)) {
|
||||
int length = match.rm_eo - match.rm_so;
|
||||
urls[*url_count] = strndup(cursor + match.rm_so, length);
|
||||
cursor += match.rm_eo;
|
||||
(*url_count)++;
|
||||
}
|
||||
regfree(®ex);
|
||||
*url_count = 0;
|
||||
while (!regexec(®ex, cursor, 1, &match, 0)) {
|
||||
int length = match.rm_eo - match.rm_so;
|
||||
urls[*url_count] = strndup(cursor + match.rm_so, length);
|
||||
cursor += match.rm_eo;
|
||||
(*url_count)++;
|
||||
}
|
||||
regfree(®ex);
|
||||
}
|
||||
|
||||
void inplace_urls_markdown_style(char **input, char **urls, char **contents, int url_count) {
|
||||
for (int i = 0; i < url_count; i++) {
|
||||
char *found = strstr(*input, urls[i]);
|
||||
if (found) {
|
||||
char *new_text = (char *)malloc(strlen(*input) + strlen(contents[i]) - strlen(urls[i]) + 1);
|
||||
strncpy(new_text, *input, found - *input);
|
||||
new_text[found - *input] = '\0';
|
||||
strcat(new_text, contents[i]);
|
||||
strcat(new_text, found + strlen(urls[i]));
|
||||
void inplace_urls_markdown_style(char **input, char **urls, char **contents,
|
||||
int url_count) {
|
||||
for (int i = 0; i < url_count; i++) {
|
||||
char *found = strstr(*input, urls[i]);
|
||||
if (found) {
|
||||
char *new_text = (char *)malloc(strlen(*input) + strlen(contents[i]) -
|
||||
strlen(urls[i]) + 1);
|
||||
strncpy(new_text, *input, found - *input);
|
||||
new_text[found - *input] = '\0';
|
||||
strcat(new_text, contents[i]);
|
||||
strcat(new_text, found + strlen(urls[i]));
|
||||
|
||||
free(*input);
|
||||
*input = new_text;
|
||||
}
|
||||
free(*input);
|
||||
*input = new_text;
|
||||
}
|
||||
}
|
||||
}
|
138
line.h
138
line.h
@ -1,102 +1,108 @@
|
||||
// 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/history.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 <glob.h>
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#define HISTORY_FILE "~/.r_history"
|
||||
|
||||
bool line_initialized = false;
|
||||
|
||||
char *get_history_file() {
|
||||
static char result[4096];
|
||||
result[0] = 0;
|
||||
|
||||
char * get_history_file(){
|
||||
static char result[4096];
|
||||
result[0] = 0;
|
||||
|
||||
char * expanded = expand_home_directory(HISTORY_FILE);
|
||||
strcpy(result, expanded);
|
||||
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) {
|
||||
static int list_index, len = 0;
|
||||
const char* commands[] = {"help", "exit", "list", "review", "refactor", "obfuscate", "!verbose","!dump", "!model","!debug", NULL};
|
||||
char *line_command_generator(const char *text, int state) {
|
||||
static int list_index, len = 0;
|
||||
const char *commands[] = {"help", "exit", "list", "review",
|
||||
"refactor", "obfuscate", "!verbose", "!dump",
|
||||
"!model", "!debug", NULL};
|
||||
|
||||
if (!state) {
|
||||
list_index = 0;
|
||||
len = strlen(text);
|
||||
if (!state) {
|
||||
list_index = 0;
|
||||
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]) {
|
||||
const char* command = commands[list_index++];
|
||||
if (strncmp(command, text, len) == 0) {
|
||||
return strdup(command);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* line_file_generator(const char* text, int state) {
|
||||
static int list_index;
|
||||
glob_t glob_result;
|
||||
char pattern[1024];
|
||||
char *line_file_generator(const char *text, int state) {
|
||||
static int list_index;
|
||||
glob_t glob_result;
|
||||
char pattern[1024];
|
||||
|
||||
if (!state) {
|
||||
list_index = 0;
|
||||
snprintf(pattern, sizeof(pattern), "%s*", text); // Create a pattern for glob
|
||||
glob(pattern, GLOB_NOSORT, NULL, &glob_result);
|
||||
}
|
||||
if (!state) {
|
||||
list_index = 0;
|
||||
snprintf(pattern, sizeof(pattern), "%s*",
|
||||
text); // Create a pattern for glob
|
||||
glob(pattern, GLOB_NOSORT, NULL, &glob_result);
|
||||
}
|
||||
|
||||
if (list_index < glob_result.gl_pathc) {
|
||||
return strdup(glob_result.gl_pathv[list_index++]);
|
||||
}
|
||||
if (list_index < glob_result.gl_pathc) {
|
||||
return strdup(glob_result.gl_pathv[list_index++]);
|
||||
}
|
||||
|
||||
globfree(&glob_result);
|
||||
return NULL;
|
||||
globfree(&glob_result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char** line_command_completion(const char* text, int start, int end) {
|
||||
rl_attempted_completion_over = 1;
|
||||
char **line_command_completion(const char *text, int start, int end) {
|
||||
rl_attempted_completion_over = 1;
|
||||
|
||||
// Check if the input is a file path
|
||||
if (start > 0 && text[0] != ' ') {
|
||||
return rl_completion_matches(text, line_file_generator);
|
||||
}
|
||||
// Check if the input is a file path
|
||||
if (start > 0 && text[0] != ' ') {
|
||||
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() {
|
||||
if (!line_initialized) {
|
||||
rl_attempted_completion_function = line_command_completion;
|
||||
line_initialized = true;
|
||||
read_history(get_history_file());
|
||||
}
|
||||
if (!line_initialized) {
|
||||
rl_attempted_completion_function = line_command_completion;
|
||||
line_initialized = true;
|
||||
read_history(get_history_file());
|
||||
}
|
||||
}
|
||||
|
||||
char* line_read(char* prefix) {
|
||||
char* data = readline(prefix);
|
||||
if (!(data && *data)) {
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
return data;
|
||||
char *line_read(char *prefix) {
|
||||
char *data = readline(prefix);
|
||||
if (!(data && *data)) {
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void line_add_history(char* data) {
|
||||
add_history(data);
|
||||
write_history(get_history_file());
|
||||
void line_add_history(char *data) {
|
||||
add_history(data);
|
||||
write_history(get_history_file());
|
||||
}
|
||||
|
529
main.c
529
main.c
@ -1,6 +1,9 @@
|
||||
// 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:
|
||||
// - openai.h
|
||||
@ -28,24 +31,22 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
#include "r.h"
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
#include "openai.h"
|
||||
#include "markdown.h"
|
||||
#include "line.h"
|
||||
#include "markdown.h"
|
||||
#include "openai.h"
|
||||
#include "utils.h"
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "utils.h"
|
||||
|
||||
#include "db_utils.h"
|
||||
|
||||
@ -56,311 +57,315 @@ bool API_MODE = false;
|
||||
void help();
|
||||
void render(char *);
|
||||
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) {
|
||||
int index = 0;
|
||||
prompt[index] = '\0';
|
||||
char c = 0;
|
||||
while ((c = getchar()) != EOF) {
|
||||
prompt[index++] = c;
|
||||
}
|
||||
prompt[index++] = '\0';
|
||||
return prompt;
|
||||
char *get_prompt_from_stdin(char *prompt) {
|
||||
int index = 0;
|
||||
prompt[index] = '\0';
|
||||
char c = 0;
|
||||
while ((c = getchar()) != EOF) {
|
||||
prompt[index++] = c;
|
||||
}
|
||||
prompt[index++] = '\0';
|
||||
return prompt;
|
||||
}
|
||||
|
||||
char *get_prompt_from_args(int c, char **argv) {
|
||||
char *prompt = (char *)malloc(1024 * 1024 * 10 + 1);
|
||||
char *system = (char *)malloc(1024*1024);
|
||||
char *prompt = (char *)malloc(1024 * 1024 * 10 + 1);
|
||||
char *system = (char *)malloc(1024 * 1024);
|
||||
|
||||
system[0] = 0;
|
||||
prompt[0] = 0;
|
||||
bool get_from_std_in = false;
|
||||
for (int i = 1; i < c; i++) {
|
||||
if (!strcmp(argv[i],"--stdin")){
|
||||
fprintf(stderr, "%s\n", "Reading from stdin.");
|
||||
get_from_std_in = true;
|
||||
}else if(!strcmp(argv[i],"--verbose")){
|
||||
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, ".");
|
||||
}
|
||||
}
|
||||
system[0] = 0;
|
||||
prompt[0] = 0;
|
||||
bool get_from_std_in = false;
|
||||
for (int i = 1; i < c; i++) {
|
||||
if (!strcmp(argv[i], "--stdin")) {
|
||||
fprintf(stderr, "%s\n", "Reading from stdin.");
|
||||
get_from_std_in = true;
|
||||
} else if (!strcmp(argv[i], "--verbose")) {
|
||||
is_verbose = true;
|
||||
}
|
||||
|
||||
if(get_from_std_in){
|
||||
if(*system){
|
||||
openai_system(system);
|
||||
}
|
||||
free(system);
|
||||
prompt = get_prompt_from_stdin(prompt);
|
||||
}else{
|
||||
free(prompt);
|
||||
prompt = system;
|
||||
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;
|
||||
}
|
||||
|
||||
if (!*prompt) {
|
||||
free(prompt);
|
||||
return NULL;
|
||||
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, ".");
|
||||
}
|
||||
}
|
||||
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[]) {
|
||||
char *prompt = get_prompt_from_args(argc, argv);
|
||||
if (prompt != NULL) {
|
||||
char *response = openai_chat("user", prompt);
|
||||
if(!response){
|
||||
printf("Could not get response from server\n");
|
||||
free(prompt);
|
||||
return false;
|
||||
}
|
||||
render(response);
|
||||
free(response);
|
||||
free(prompt);
|
||||
return true;
|
||||
char *prompt = get_prompt_from_args(argc, argv);
|
||||
if (prompt != NULL) {
|
||||
char *response = openai_chat("user", prompt);
|
||||
if (!response) {
|
||||
printf("Could not get response from server\n");
|
||||
free(prompt);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
render(response);
|
||||
free(response);
|
||||
free(prompt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void serve() {
|
||||
render("Starting server. *Put executables in a dir named cgi-bin and they will behave as web pages.*");
|
||||
int res = system("python3 -m http.server --cgi");
|
||||
(void)res;
|
||||
render("Starting server. *Put executables in a dir named cgi-bin and they "
|
||||
"will behave as web pages.*");
|
||||
int res = system("python3 -m http.server --cgi");
|
||||
(void)res;
|
||||
}
|
||||
|
||||
char ** get_parameters(char * content, char * delimiter){
|
||||
char * start = NULL;
|
||||
char ** parameters = NULL; //(char **)malloc(sizeof(char *) * 2);
|
||||
int count = 0;
|
||||
while((start = strstr(content, delimiter)) != NULL){
|
||||
start += 3;
|
||||
char * end = strstr(start, delimiter);
|
||||
char * parameter = (char *)malloc(end - start + 1);
|
||||
char **get_parameters(char *content, char *delimiter) {
|
||||
char *start = NULL;
|
||||
char **parameters = NULL; //(char **)malloc(sizeof(char *) * 2);
|
||||
int count = 0;
|
||||
while ((start = strstr(content, delimiter)) != NULL) {
|
||||
start += 3;
|
||||
char *end = strstr(start, delimiter);
|
||||
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);
|
||||
content = end + 3;
|
||||
count+=1;
|
||||
parameters = (char **)realloc(parameters, sizeof(char *) * (1+count*2));
|
||||
parameters[count-1] = parameter;
|
||||
parameters[count] = NULL;
|
||||
content = end + 3;
|
||||
count += 1;
|
||||
parameters = (char **)realloc(parameters, sizeof(char *) * (1 + count * 2));
|
||||
parameters[count - 1] = parameter;
|
||||
parameters[count] = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return parameters;
|
||||
return parameters;
|
||||
}
|
||||
|
||||
void render(char *content)
|
||||
{
|
||||
void render(char *content) {
|
||||
|
||||
if(SYNTAX_HIGHLIGHT_ENABLED)
|
||||
{
|
||||
parse_markdown_to_ansi(content);
|
||||
}else{
|
||||
printf("%s", content);
|
||||
}
|
||||
if (SYNTAX_HIGHLIGHT_ENABLED) {
|
||||
parse_markdown_to_ansi(content);
|
||||
} else {
|
||||
printf("%s", content);
|
||||
}
|
||||
}
|
||||
|
||||
void repl() {
|
||||
line_init();
|
||||
char *line = NULL;
|
||||
//char *previous_line = NULL;
|
||||
while (true) {
|
||||
line = line_read("> ");
|
||||
if (!line || !*line) {
|
||||
continue;
|
||||
//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);
|
||||
|
||||
}
|
||||
}
|
||||
line_init();
|
||||
char *line = NULL;
|
||||
// char *previous_line = NULL;
|
||||
while (true) {
|
||||
line = line_read("> ");
|
||||
if (!line || !*line) {
|
||||
continue;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void help() {
|
||||
char help_text[1024 * 1024] = {0};
|
||||
char *template = "# Help\n"
|
||||
"Written by retoor@molodetz.nl.\n\n"
|
||||
"## Features\n"
|
||||
" - navigate through history using `arrows`.\n"
|
||||
" - navigate through history with **recursive search** using `ctrl+r`.\n"
|
||||
" - **inception with python** for *incoming* and *outgoing* content.\n"
|
||||
" - markdown and **syntax highlighting**.\n"
|
||||
" - **execute python commands** with prefix `!`\n"
|
||||
" - list files of the current work directory using `ls`.\n"
|
||||
" - type `serve` to start a web server with directory listing. Easy for network transfers.\n\n"
|
||||
"## Configuration\n"
|
||||
" - model temperature is %f.\n"
|
||||
" - model name is %s.\n"
|
||||
" - max tokens is %d.\n\n"
|
||||
"## In development\n"
|
||||
" - **google search** and actions with those results.\n"
|
||||
" - **reminders**.\n"
|
||||
" - 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 help_text[1024 * 1024] = {0};
|
||||
char *template =
|
||||
"# Help\n"
|
||||
"Written by retoor@molodetz.nl.\n\n"
|
||||
"## Features\n"
|
||||
" - navigate through history using `arrows`.\n"
|
||||
" - navigate through history with **recursive search** using `ctrl+r`.\n"
|
||||
" - **inception with python** for *incoming* and *outgoing* content.\n"
|
||||
" - markdown and **syntax highlighting**.\n"
|
||||
" - **execute python commands** with prefix `!`\n"
|
||||
" - list files of the current work directory using `ls`.\n"
|
||||
" - type `serve` to start a web server with directory listing. Easy for "
|
||||
"network transfers.\n\n"
|
||||
"## Configuration\n"
|
||||
" - model temperature is %f.\n"
|
||||
" - model name is %s.\n"
|
||||
" - max tokens is %d.\n\n"
|
||||
"## In development\n"
|
||||
" - **google search** and actions with those results.\n"
|
||||
" - **reminders**.\n"
|
||||
" - 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 * pos = strstr(content, what);
|
||||
if(!pos){
|
||||
return strdup(content);
|
||||
}
|
||||
char * result = (char *)malloc(strlen(content) + strlen(with) + 5);
|
||||
memset(result, 0, strlen(content) + strlen(with) + 3);
|
||||
memcpy(result, content, pos - content);
|
||||
memcpy(result + (pos - content), with, strlen(with));
|
||||
memcpy(result + (pos - content) + strlen(with), pos + strlen(what), strlen(content) - (pos - content) - strlen(what) + 1);
|
||||
return result;
|
||||
char *strreplace(char *content, char *what, char *with) {
|
||||
char *pos = strstr(content, what);
|
||||
if (!pos) {
|
||||
return strdup(content);
|
||||
}
|
||||
char *result = (char *)malloc(strlen(content) + strlen(with) + 5);
|
||||
memset(result, 0, strlen(content) + strlen(with) + 3);
|
||||
memcpy(result, content, pos - content);
|
||||
memcpy(result + (pos - content), with, strlen(with));
|
||||
memcpy(result + (pos - content) + strlen(with), pos + strlen(what),
|
||||
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 "
|
||||
"user into shell commands that will be executed on a debian "
|
||||
"based system. You can execute shell commands by responding with python code: "
|
||||
"literally `\"\"\"!system\"\"\",\"\"\"`your shell command`\"\"\". Execute 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.";
|
||||
|
||||
|
||||
|
||||
|
||||
"based system. You can execute shell commands by responding with python "
|
||||
"code: "
|
||||
"literally `\"\"\"!system\"\"\",\"\"\"`your shell command`\"\"\". Execute "
|
||||
"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) {
|
||||
char * file_content = read_file(path);
|
||||
if(!file_content){
|
||||
return false;
|
||||
}
|
||||
openai_system(file_content);
|
||||
free(file_content);
|
||||
return true;
|
||||
char *file_content = read_file(path);
|
||||
if (!file_content) {
|
||||
return false;
|
||||
}
|
||||
openai_system(file_content);
|
||||
free(file_content);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void init() {
|
||||
setbuf(stdout, NULL);
|
||||
line_init();
|
||||
auth_init();
|
||||
db_initialize();
|
||||
char * schema = db_get_schema();
|
||||
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);
|
||||
free(schema);
|
||||
fprintf(stderr, "%s", "Loading... ⏳");
|
||||
openai_system(payload);
|
||||
if(!openai_include(".rcontext.txt")){
|
||||
openai_include("~/.rcontext.txt");
|
||||
}
|
||||
fprintf(stderr, "\r \r");
|
||||
setbuf(stdout, NULL);
|
||||
line_init();
|
||||
auth_init();
|
||||
db_initialize();
|
||||
char *schema = db_get_schema();
|
||||
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);
|
||||
free(schema);
|
||||
fprintf(stderr, "%s", "Loading... ⏳");
|
||||
openai_system(payload);
|
||||
if (!openai_include(".rcontext.txt")) {
|
||||
openai_include("~/.rcontext.txt");
|
||||
}
|
||||
fprintf(stderr, "\r \r");
|
||||
}
|
||||
|
||||
void handle_sigint(int sig) {
|
||||
time_t current_time = time(NULL);
|
||||
printf("\n");
|
||||
if (sigint_count == 0) {
|
||||
first_sigint_time = current_time;
|
||||
sigint_count++;
|
||||
time_t current_time = time(NULL);
|
||||
printf("\n");
|
||||
if (sigint_count == 0) {
|
||||
first_sigint_time = current_time;
|
||||
sigint_count++;
|
||||
} else {
|
||||
if (difftime(current_time, first_sigint_time) <= 1) {
|
||||
exit(0);
|
||||
} else {
|
||||
if (difftime(current_time, first_sigint_time) <= 1) {
|
||||
exit(0);
|
||||
} else {
|
||||
sigint_count = 1;
|
||||
first_sigint_time = current_time;
|
||||
}
|
||||
sigint_count = 1;
|
||||
first_sigint_time = current_time;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
signal(SIGINT, handle_sigint);
|
||||
signal(SIGINT, handle_sigint);
|
||||
|
||||
init();
|
||||
if (try_prompt(argc, argv))
|
||||
return 0;
|
||||
|
||||
repl();
|
||||
init();
|
||||
if (try_prompt(argc, argv))
|
||||
return 0;
|
||||
|
||||
repl();
|
||||
return 0;
|
||||
}
|
||||
|
298
markdown.h
298
markdown.h
@ -1,8 +1,11 @@
|
||||
// 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:
|
||||
// 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
|
||||
// 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 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,
|
||||
@ -23,9 +26,9 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define RESET "\033[0m"
|
||||
#define BOLD "\033[1m"
|
||||
@ -35,153 +38,164 @@
|
||||
#define FG_CYAN "\033[36m"
|
||||
|
||||
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++) {
|
||||
if (strcmp(word, keywords[i]) == 0) {
|
||||
return 1;
|
||||
}
|
||||
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++) {
|
||||
if (strcmp(word, keywords[i]) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void highlight_code(const char *code) {
|
||||
const char *ptr = code;
|
||||
char buffer[4096];
|
||||
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;
|
||||
const char *ptr = code;
|
||||
char buffer[4096];
|
||||
size_t index = 0;
|
||||
|
||||
if (is_keyword(buffer)) {
|
||||
printf(FG_BLUE "%s" RESET, buffer);
|
||||
} else {
|
||||
printf("%s", buffer);
|
||||
}
|
||||
index = 0;
|
||||
} 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++;
|
||||
}
|
||||
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)) {
|
||||
printf(FG_BLUE "%s" RESET, buffer);
|
||||
} else {
|
||||
printf("%s", buffer);
|
||||
}
|
||||
index = 0;
|
||||
} 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) {
|
||||
const char *ptr = markdown;
|
||||
bool inside_code = false;
|
||||
const char *ptr = markdown;
|
||||
bool inside_code = false;
|
||||
|
||||
while (*ptr) {
|
||||
if (*ptr == '`' && *(ptr + 1) != '`') {
|
||||
inside_code = !inside_code;
|
||||
if (inside_code) {
|
||||
printf(FG_YELLOW);
|
||||
} else {
|
||||
printf(RESET);
|
||||
}
|
||||
ptr++;
|
||||
continue;
|
||||
}else if(!strncmp(ptr, "```", 3)) {
|
||||
inside_code = !inside_code;
|
||||
if(inside_code){
|
||||
ptr = strstr(ptr, "\n") + 1;
|
||||
}else{
|
||||
ptr+=3;
|
||||
}
|
||||
if(*ptr == '\0'){
|
||||
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++;
|
||||
}
|
||||
}
|
||||
while (*ptr) {
|
||||
if (*ptr == '`' && *(ptr + 1) != '`') {
|
||||
inside_code = !inside_code;
|
||||
if (inside_code) {
|
||||
printf(FG_YELLOW);
|
||||
} else {
|
||||
printf(RESET);
|
||||
}
|
||||
ptr++;
|
||||
continue;
|
||||
} else if (!strncmp(ptr, "```", 3)) {
|
||||
inside_code = !inside_code;
|
||||
if (inside_code) {
|
||||
ptr = strstr(ptr, "\n") + 1;
|
||||
} else {
|
||||
ptr += 3;
|
||||
}
|
||||
if (*ptr == '\0') {
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
110
messages.h
110
messages.h
@ -1,90 +1,106 @@
|
||||
// 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
|
||||
|
||||
// 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_MESSAGES_H
|
||||
#define R_MESSAGES_H
|
||||
|
||||
#include <string.h>
|
||||
#include "tools.h"
|
||||
#include "json-c/json.h"
|
||||
#include "tools.h"
|
||||
#include <string.h>
|
||||
|
||||
struct json_object *message_array = NULL;
|
||||
|
||||
struct json_object *message_list() {
|
||||
if (!message_array) {
|
||||
message_array = json_object_new_array();
|
||||
}
|
||||
return message_array;
|
||||
if (!message_array) {
|
||||
message_array = json_object_new_array();
|
||||
}
|
||||
return message_array;
|
||||
}
|
||||
bool messages_remove_last() {
|
||||
struct json_object *messages = message_list();
|
||||
int size = json_object_array_length(messages);
|
||||
if (size) {
|
||||
json_object_array_del_idx(messages, size - 1, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
struct json_object *messages = message_list();
|
||||
int size = json_object_array_length(messages);
|
||||
if (size) {
|
||||
json_object_array_del_idx(messages, size - 1, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void messages_remove(){
|
||||
while(messages_remove_last())
|
||||
continue;
|
||||
void messages_remove() {
|
||||
while (messages_remove_last())
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
struct json_object *message_add_tool_call(struct json_object *message) {
|
||||
struct json_object *messages = message_list();
|
||||
json_object_array_add(messages, message);
|
||||
return message;
|
||||
struct json_object *messages = message_list();
|
||||
json_object_array_add(messages, message);
|
||||
return message;
|
||||
}
|
||||
|
||||
struct json_object *message_add_tool_result(const char *tool_call_id, const char *tool_result) {
|
||||
struct json_object *messages = message_list();
|
||||
struct json_object *message = json_object_new_object();
|
||||
struct json_object *message_add_tool_result(const char *tool_call_id,
|
||||
const char *tool_result) {
|
||||
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_result", json_object_new_string(tool_result));
|
||||
json_object_object_add(message, "tool_call_id",
|
||||
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);
|
||||
return message;
|
||||
json_object_array_add(messages, message);
|
||||
return message;
|
||||
}
|
||||
|
||||
void message_add_object(json_object *message) {
|
||||
struct json_object *messages = message_list();
|
||||
json_object_array_add(messages, message);
|
||||
struct json_object *messages = message_list();
|
||||
json_object_array_add(messages, message);
|
||||
}
|
||||
|
||||
struct json_object *message_add(const char *role, const char *content) {
|
||||
struct json_object *messages = message_list();
|
||||
struct json_object *message = json_object_new_object();
|
||||
json_object_object_add(message, "role", json_object_new_string(role));
|
||||
json_object_object_add(message, "content", json_object_new_string(content));
|
||||
struct json_object *messages = message_list();
|
||||
struct json_object *message = json_object_new_object();
|
||||
json_object_object_add(message, "role", json_object_new_string(role));
|
||||
json_object_object_add(message, "content", json_object_new_string(content));
|
||||
|
||||
if (!strcmp(role, "user")) {
|
||||
json_object_object_add(message, "tools", tools_descriptions());
|
||||
}
|
||||
if (!strcmp(role, "user")) {
|
||||
json_object_object_add(message, "tools", tools_descriptions());
|
||||
}
|
||||
|
||||
json_object_array_add(messages, message);
|
||||
return message;
|
||||
json_object_array_add(messages, message);
|
||||
return message;
|
||||
}
|
||||
|
||||
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() {
|
||||
if (message_array) {
|
||||
json_object_put(message_array);
|
||||
message_array = NULL;
|
||||
}
|
||||
if (message_array) {
|
||||
json_object_put(message_array);
|
||||
message_array = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
179
openai.h
179
openai.h
@ -1,8 +1,11 @@
|
||||
// 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
|
||||
//
|
||||
@ -15,8 +18,8 @@
|
||||
// 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 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,
|
||||
@ -26,109 +29,113 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
|
||||
#ifndef R_OPENAI_H
|
||||
#define R_OPENAI_H
|
||||
|
||||
#include "chat.h"
|
||||
#include "http_curl.h"
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
char* openai_fetch_models() {
|
||||
const char* api_url = "https://api.openai.com/v1/models";
|
||||
return curl_get(api_url);
|
||||
char *openai_fetch_models() {
|
||||
const char *api_url = "https://api.openai.com/v1/models";
|
||||
return curl_get(api_url);
|
||||
}
|
||||
|
||||
bool openai_system(char* message_content) {
|
||||
chat_json("system", message_content);
|
||||
return true;
|
||||
bool openai_system(char *message_content) {
|
||||
chat_json("system", message_content);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct json_object* openai_process_chat_message(const char* api_url, const char* json_data) {
|
||||
char* response = curl_post(api_url, json_data);
|
||||
struct json_object* parsed_json = json_tokener_parse(response);
|
||||
if (!parsed_json) {
|
||||
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 *openai_process_chat_message(const char *api_url,
|
||||
const char *json_data) {
|
||||
char *response = curl_post(api_url, json_data);
|
||||
struct json_object *parsed_json = json_tokener_parse(response);
|
||||
if (!parsed_json) {
|
||||
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)) {
|
||||
|
||||
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: ");
|
||||
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();
|
||||
fprintf(stderr, "%s\n", json_object_to_json_string(parsed_json));
|
||||
|
||||
messages_remove_last();
|
||||
json_object_put(parsed_json);
|
||||
messages_remove_last();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
messages_remove_last();
|
||||
|
||||
struct json_object* choices_array;
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
struct json_object* first_choice = json_object_array_get_idx(choices_array, 0);
|
||||
if (!first_choice) {
|
||||
fprintf(stderr, "Failed to get the first element of 'choices'.\n");
|
||||
json_object_put(parsed_json);
|
||||
return NULL;
|
||||
}
|
||||
struct json_object* message_object;
|
||||
if (!json_object_object_get_ex(first_choice, "message", &message_object)) {
|
||||
fprintf(stderr, "Failed to get 'message' object.\n");
|
||||
json_object_put(parsed_json);
|
||||
return NULL;
|
||||
}
|
||||
return message_object;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct json_object *choices_array;
|
||||
if (!json_object_object_get_ex(parsed_json, "choices", &choices_array)) {
|
||||
fprintf(stderr, "Failed to get 'choices' array.\n%s\n", response);
|
||||
json_object_put(parsed_json);
|
||||
return NULL;
|
||||
}
|
||||
struct json_object *first_choice =
|
||||
json_object_array_get_idx(choices_array, 0);
|
||||
if (!first_choice) {
|
||||
fprintf(stderr, "Failed to get the first element of 'choices'.\n");
|
||||
json_object_put(parsed_json);
|
||||
return NULL;
|
||||
}
|
||||
struct json_object *message_object;
|
||||
if (!json_object_object_get_ex(first_choice, "message", &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) {
|
||||
if(message_content == NULL || *message_content == '\0' || *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);
|
||||
|
||||
struct json_object* message_object = openai_process_chat_message(api_url, json_data);
|
||||
message_add_object(message_object);
|
||||
if (message_object == NULL) {
|
||||
printf("ERROR + NULL IS SUCCESS\n");
|
||||
return NULL;
|
||||
}
|
||||
struct json_object* tool_calls;
|
||||
json_object_object_get_ex(message_object, "tool_calls", &tool_calls);
|
||||
if (tool_calls) {
|
||||
char *openai_chat(const char *user_role, const char *message_content) {
|
||||
if (message_content == NULL || *message_content == '\0' ||
|
||||
*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);
|
||||
|
||||
struct json_object *message_object =
|
||||
openai_process_chat_message(api_url, json_data);
|
||||
message_add_object(message_object);
|
||||
if (message_object == NULL) {
|
||||
printf("ERROR + NULL IS SUCCESS\n");
|
||||
return NULL;
|
||||
}
|
||||
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);
|
||||
struct json_object* tool_call_results = tools_execute(tool_calls);
|
||||
int results_count = json_object_array_length(tool_call_results);
|
||||
for (int i = 0; i < results_count; i++) {
|
||||
struct json_object* tool_call_result = json_object_array_get_idx(tool_call_results, i);
|
||||
message_add_tool_call(tool_call_result);
|
||||
}
|
||||
char* tool_calls_result_str = chat_json(NULL, NULL);
|
||||
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);
|
||||
struct json_object *tool_call_results = tools_execute(tool_calls);
|
||||
int results_count = json_object_array_length(tool_call_results);
|
||||
for (int i = 0; i < results_count; i++) {
|
||||
struct json_object *tool_call_result =
|
||||
json_object_array_get_idx(tool_call_results, i);
|
||||
message_add_tool_call(tool_call_result);
|
||||
}
|
||||
const char* content_str = json_object_get_string(json_object_object_get(message_object, "content"));
|
||||
return strdup(content_str);
|
||||
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"));
|
||||
return strdup(content_str);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
74
plugin.h
74
plugin.h
@ -1,58 +1,62 @@
|
||||
// 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
|
||||
|
||||
|
||||
#include <Python.h>
|
||||
#include <structmember.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <structmember.h>
|
||||
|
||||
bool plugin_initialized = false;
|
||||
|
||||
bool plugin_construct() {
|
||||
if (plugin_initialized) return true;
|
||||
|
||||
Py_Initialize();
|
||||
if (!Py_IsInitialized()) {
|
||||
fprintf(stderr, "Failed to initialize the Python interpreter\n");
|
||||
return false;
|
||||
}
|
||||
plugin_initialized = true;
|
||||
if (plugin_initialized)
|
||||
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) {
|
||||
plugin_construct();
|
||||
/*const char *basics =
|
||||
"import sys\n"
|
||||
"import os\n"
|
||||
"from os import *\n"
|
||||
"import math\n"
|
||||
"import pathlib\n"
|
||||
"from pathlib import Path\n"
|
||||
"import re\n"
|
||||
"import subprocess\n"
|
||||
"from subprocess import *\n"
|
||||
"import time\n"
|
||||
"from datetime import datetime\n"
|
||||
"%s";
|
||||
*/
|
||||
const char *basics = "\n\n";
|
||||
size_t length = strlen(basics) + strlen(src);
|
||||
char *script = malloc(length + 1);
|
||||
sprintf(script, basics, src);
|
||||
script[length] = '\0';
|
||||
PyRun_SimpleString(script);
|
||||
free(script);
|
||||
plugin_construct();
|
||||
/*const char *basics =
|
||||
"import sys\n"
|
||||
"import os\n"
|
||||
"from os import *\n"
|
||||
"import math\n"
|
||||
"import pathlib\n"
|
||||
"from pathlib import Path\n"
|
||||
"import re\n"
|
||||
"import subprocess\n"
|
||||
"from subprocess import *\n"
|
||||
"import time\n"
|
||||
"from datetime import datetime\n"
|
||||
"%s";
|
||||
*/
|
||||
const char *basics = "\n\n";
|
||||
size_t length = strlen(basics) + strlen(src);
|
||||
char *script = malloc(length + 1);
|
||||
sprintf(script, basics, src);
|
||||
script[length] = '\0';
|
||||
PyRun_SimpleString(script);
|
||||
free(script);
|
||||
}
|
||||
|
||||
void plugin_destruct() {
|
||||
if (plugin_initialized) Py_Finalize();
|
||||
if (plugin_initialized)
|
||||
Py_Finalize();
|
||||
}
|
||||
|
36
r.h
36
r.h
@ -1,38 +1,34 @@
|
||||
#ifndef R_H
|
||||
#define R_H
|
||||
#include "auth.h"
|
||||
#include "malloc.h"
|
||||
#include "utils.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
#include "auth.h"
|
||||
bool is_verbose = false;
|
||||
|
||||
char * _model = NULL;
|
||||
char *_model = NULL;
|
||||
|
||||
#define DB_FILE "~/.r.db"
|
||||
static int prompt_max_tokens = 10000;
|
||||
#define PROMPT_TEMPERATURE 0.1
|
||||
|
||||
|
||||
|
||||
|
||||
void set_prompt_model(const char *model) {
|
||||
if(_model != NULL) {
|
||||
free(_model);
|
||||
}
|
||||
_model = strdup(model);
|
||||
if (_model != NULL) {
|
||||
free(_model);
|
||||
}
|
||||
_model = strdup(model);
|
||||
}
|
||||
|
||||
const char * get_prompt_model() {
|
||||
if(auth_type != AUTH_TYPE_API_KEY) {
|
||||
if(_model == NULL) {
|
||||
_model = strdup("gpt-3.5-turbo");
|
||||
}
|
||||
} else if(_model == NULL) {
|
||||
_model = strdup("gpt-4o-mini");
|
||||
const char *get_prompt_model() {
|
||||
if (auth_type != AUTH_TYPE_API_KEY) {
|
||||
if (_model == NULL) {
|
||||
_model = strdup("gpt-3.5-turbo");
|
||||
}
|
||||
return _model;
|
||||
} else if (_model == NULL) {
|
||||
_model = strdup("gpt-4o-mini");
|
||||
}
|
||||
return _model;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
113
rpylib.c
113
rpylib.c
@ -1,28 +1,29 @@
|
||||
/* Written by retoor@molodetz.nl */
|
||||
|
||||
/*
|
||||
This C extension for Python provides a simple API for communication with an OpenAI service.
|
||||
It includes functions to return a "Hello World" string, conduct a chat session through OpenAI, and reset the message history.
|
||||
/*
|
||||
This C extension for Python provides a simple API for communication with an
|
||||
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:
|
||||
- <Python.h>: Includes necessary Python headers to create a C extension.
|
||||
- "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
|
||||
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
|
||||
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.
|
||||
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,
|
||||
@ -34,72 +35,66 @@ SOFTWARE.
|
||||
*/
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#include "openai.h"
|
||||
#include "auth.h"
|
||||
#include "openai.h"
|
||||
#include <Python.h>
|
||||
|
||||
static PyObject* rpylib_reset(PyObject *self, PyObject *args) {
|
||||
return PyUnicode_FromString("True");
|
||||
static PyObject *rpylib_reset(PyObject *self, PyObject *args) {
|
||||
return PyUnicode_FromString("True");
|
||||
}
|
||||
|
||||
static PyObject* rpylib_chat(PyObject *self, PyObject *args) {
|
||||
const char *role, *message;
|
||||
|
||||
|
||||
printf("That goes alright! 1\n");
|
||||
if (!PyArg_ParseTuple(args, "ss", &role, &message)) {
|
||||
return NULL;
|
||||
}
|
||||
printf("That goes alright! 2\n");
|
||||
char *result = openai_chat(role, message);
|
||||
PyObject *py_result = PyUnicode_FromString(result);
|
||||
free(result);
|
||||
return py_result;
|
||||
static PyObject *rpylib_chat(PyObject *self, PyObject *args) {
|
||||
const char *role, *message;
|
||||
|
||||
printf("That goes alright! 1\n");
|
||||
if (!PyArg_ParseTuple(args, "ss", &role, &message)) {
|
||||
return NULL;
|
||||
}
|
||||
printf("That goes alright! 2\n");
|
||||
char *result = openai_chat(role, message);
|
||||
PyObject *py_result = PyUnicode_FromString(result);
|
||||
free(result);
|
||||
return py_result;
|
||||
}
|
||||
static PyObject* rpylib_prompt(PyObject *self, PyObject *args) {
|
||||
const char *role = "user";
|
||||
const char *message;
|
||||
if (!PyArg_ParseTuple(args, "s", &message)) {
|
||||
return NULL;
|
||||
}
|
||||
char *result = openai_chat(role, message);
|
||||
PyObject *py_result = PyUnicode_FromString(result);
|
||||
free(result);
|
||||
return py_result;
|
||||
static PyObject *rpylib_prompt(PyObject *self, PyObject *args) {
|
||||
const char *role = "user";
|
||||
const char *message;
|
||||
if (!PyArg_ParseTuple(args, "s", &message)) {
|
||||
return NULL;
|
||||
}
|
||||
char *result = openai_chat(role, message);
|
||||
PyObject *py_result = PyUnicode_FromString(result);
|
||||
free(result);
|
||||
return py_result;
|
||||
}
|
||||
static PyObject* rpylib_system(PyObject *self, PyObject *args) {
|
||||
const char *role = "system";
|
||||
const char *message;
|
||||
if (!PyArg_ParseTuple(args, "s", &message)) {
|
||||
return NULL;
|
||||
}
|
||||
char *result = openai_chat(role, message);
|
||||
PyObject *py_result = PyUnicode_FromString(result);
|
||||
free(result);
|
||||
return py_result;
|
||||
static PyObject *rpylib_system(PyObject *self, PyObject *args) {
|
||||
const char *role = "system";
|
||||
const char *message;
|
||||
if (!PyArg_ParseTuple(args, "s", &message)) {
|
||||
return NULL;
|
||||
}
|
||||
char *result = openai_chat(role, message);
|
||||
PyObject *py_result = PyUnicode_FromString(result);
|
||||
free(result);
|
||||
return py_result;
|
||||
}
|
||||
static PyMethodDef MyModuleMethods[] = {
|
||||
{"chat", rpylib_chat, METH_VARARGS, "Chat with OpenAI."},
|
||||
//{"prompt", rpylib_prompt, METH_VARARGS, "Prompt to OpenAI."},
|
||||
//{"system", rpylib_system, METH_VARARGS, "Add system message."},
|
||||
{"reset", rpylib_reset, METH_NOARGS, "Reset message history."},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
{NULL, NULL, 0, NULL}};
|
||||
|
||||
static struct PyModuleDef rpylib = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"rpylib",
|
||||
"R - the power of R in Python, made by retoor.",
|
||||
-1,
|
||||
MyModuleMethods
|
||||
};
|
||||
PyModuleDef_HEAD_INIT, "rpylib",
|
||||
"R - the power of R in Python, made by retoor.", -1, MyModuleMethods};
|
||||
|
||||
PyMODINIT_FUNC PyInit_rpylib(void) {
|
||||
|
||||
auth_init();
|
||||
|
||||
printf("Init\n");
|
||||
void * res = PyModule_Create(&rpylib);
|
||||
printf("GLOB\n");
|
||||
return res;
|
||||
auth_init();
|
||||
|
||||
printf("Init\n");
|
||||
void *res = PyModule_Create(&rpylib);
|
||||
printf("GLOB\n");
|
||||
return res;
|
||||
}
|
||||
|
129
url.h
129
url.h
@ -1,85 +1,102 @@
|
||||
// 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
|
||||
// - <string.h> for string manipulation functions
|
||||
// - <stdlib.h> for memory allocation and management
|
||||
|
||||
// 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
|
||||
#define R_URL_H
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
char scheme[16];
|
||||
char hostname[256];
|
||||
char port[8];
|
||||
char path[512];
|
||||
char query[512];
|
||||
char scheme[16];
|
||||
char hostname[256];
|
||||
char port[8];
|
||||
char path[512];
|
||||
char query[512];
|
||||
} url_t;
|
||||
|
||||
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, "://");
|
||||
if (!scheme_end) {
|
||||
return -1;
|
||||
const char *scheme_end = strstr(url, "://");
|
||||
if (!scheme_end) {
|
||||
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);
|
||||
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';
|
||||
|
||||
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';
|
||||
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;
|
||||
}
|
||||
|
||||
if (path_start) {
|
||||
if (query_start) {
|
||||
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);
|
||||
}
|
||||
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';
|
||||
}
|
||||
|
||||
if (path_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
|
104
utils.h
104
utils.h
@ -1,69 +1,77 @@
|
||||
// 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
|
||||
//
|
||||
// Permission is granted to use, copy, modify, merge, distribute, sublicense, 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.
|
||||
// Permission is granted to use, copy, modify, merge, distribute, sublicense,
|
||||
// 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
|
||||
#define UTILS_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char* expand_home_directory(const char* path) {
|
||||
if (path == NULL) return NULL;
|
||||
char *expand_home_directory(const char *path) {
|
||||
if (path == NULL)
|
||||
return NULL;
|
||||
|
||||
if (path[0] == '~' && path[1] == '/') {
|
||||
const char* home_dir = getenv("HOME");
|
||||
if (home_dir == NULL) {
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
if (pw == NULL) 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);
|
||||
if (path[0] == '~' && path[1] == '/') {
|
||||
const char *home_dir = getenv("HOME");
|
||||
if (home_dir == NULL) {
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
if (pw == NULL)
|
||||
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);
|
||||
}
|
||||
}
|
||||
char * read_file(const char * path) {
|
||||
char * expanded_path = expand_home_directory(path);
|
||||
FILE *file = fopen(expanded_path, "r");
|
||||
free(expanded_path);
|
||||
if (file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
long size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
char *read_file(const char *path) {
|
||||
char *expanded_path = expand_home_directory(path);
|
||||
FILE *file = fopen(expanded_path, "r");
|
||||
free(expanded_path);
|
||||
if (file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
long size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
char *buffer = (char *)malloc(size + 1);
|
||||
size_t read = fread(buffer, 1, size, file);
|
||||
if (read == 0) {
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
char *buffer = (char *)malloc(size + 1);
|
||||
size_t read = fread(buffer, 1, size, file);
|
||||
if (read == 0) {
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
buffer[read] = '\0';
|
||||
return buffer;
|
||||
fclose(file);
|
||||
buffer[read] = '\0';
|
||||
return buffer;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user