# include "r.h"
# include <signal.h>
# include <stdbool.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <locale.h>
# include <unistd.h>
# include "line.h"
# include "markdown.h"
# include "openai.h"
# include "utils.h"
# include "db_utils.h"
# include "tools.h"
volatile sig_atomic_t sigint_count = 0 ;
time_t first_sigint_time = 0 ;
bool SYNTAX_HIGHLIGHT_ENABLED = true ;
bool API_MODE = false ;
void help ( ) ;
void render ( const char * ) ;
bool openai_include ( const char * ) ;
char * strreplace ( const char * , const char * , const char * ) ;
char * get_prompt_from_stdin ( char * prompt ) {
int index = 0 ;
char c ;
while ( ( c = getchar ( ) ) ! = EOF ) {
prompt [ index + + ] = c ;
}
prompt [ index ] = ' \0 ' ;
return prompt ;
}
char * get_prompt_from_args ( int argc , char * * argv ) {
char * prompt = malloc ( 10 * 1024 * 1024 + 1 ) ;
char * system = malloc ( 1024 * 1024 ) ;
if ( ! prompt | | ! system ) {
fprintf ( stderr , " Error: Memory allocation failed. \n " ) ;
free ( prompt ) ;
free ( system ) ;
return NULL ;
}
bool get_from_std_in = false ;
for ( int i = 1 ; i < argc ; i + + ) {
if ( strcmp ( argv [ i ] , " --stdin " ) = = 0 ) {
fprintf ( stderr , " Reading from stdin. \n " ) ;
get_from_std_in = true ;
} else if ( strcmp ( argv [ i ] , " --verbose " ) = = 0 ) {
is_verbose = true ;
} else if ( strcmp ( argv [ i ] , " --py " ) = = 0 & & i + 1 < argc ) {
char * py_file_path = expand_home_directory ( argv [ + + i ] ) ;
fprintf ( stderr , " Including \" %s \" . \n " , py_file_path ) ;
openai_include ( py_file_path ) ;
free ( py_file_path ) ;
} else if ( strcmp ( argv [ i ] , " --free " ) = = 0 ) {
auth_free ( ) ;
} else if ( strcmp ( argv [ i ] , " --context " ) = = 0 & & i + 1 < argc ) {
char * context_file_path = argv [ + + i ] ;
fprintf ( stderr , " Including \" %s \" . \n " , context_file_path ) ;
openai_include ( context_file_path ) ;
} else if ( strcmp ( argv [ i ] , " --api " ) = = 0 ) {
API_MODE = true ;
} else if ( strcmp ( argv [ i ] , " --nh " ) = = 0 ) {
SYNTAX_HIGHLIGHT_ENABLED = false ;
fprintf ( stderr , " Syntax highlighting disabled. \n " ) ;
} else {
strcat ( system , argv [ i ] ) ;
strcat ( system , ( i < argc - 1 ) ? " " : " . " ) ;
}
}
if ( get_from_std_in ) {
if ( * system ) openai_system ( 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 ) {
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 ;
}
return false ;
}
char * * get_parameters ( const char * content , const char * delimiter ) {
char * start = NULL ;
char * * parameters = NULL ;
int count = 0 ;
while ( ( start = strstr ( content , delimiter ) ) ! = NULL ) {
start + = 3 ;
char * end = strstr ( start , delimiter ) ;
char * parameter = malloc ( end - start + 1 ) ;
memcpy ( parameter , start , end - start ) ;
parameter [ end - start ] = ' \0 ' ;
content = end + 3 ;
count + + ;
parameters = realloc ( parameters , sizeof ( char * ) * ( count + 1 ) ) ;
parameters [ count - 1 ] = parameter ;
parameters [ count ] = NULL ;
}
return parameters ;
}
void render ( const char * content ) {
if ( SYNTAX_HIGHLIGHT_ENABLED ) {
parse_markdown_to_ansi ( content ) ;
} else {
printf ( " %s " , content ) ;
}
}
void repl ( ) {
line_init ( ) ;
char * line = NULL ;
while ( true ) {
line = line_read ( " > " ) ;
if ( ! line | | ! * line ) continue ;
if ( ! strncmp ( line , " !dump " , 5 ) ) {
printf ( " %s \n " , message_json ( ) ) ;
continue ;
}
if ( ! strncmp ( line , " !verbose " , 8 ) ) {
is_verbose = ! is_verbose ;
fprintf ( stderr , " %s \n " , is_verbose ? " Verbose mode enabled " : " Verbose mode disabled " ) ;
continue ;
}
if ( line & & * line ! = ' \n ' ) line_add_history ( line ) ;
if ( ! strncmp ( line , " !tools " , 6 ) ) {
printf ( " Available tools: %s \n " , json_object_to_json_string ( tools_descriptions ( ) ) ) ;
continue ;
}
if ( ! strncmp ( line , " !models " , 7 ) ) {
printf ( " Current model: %s \n " , openai_fetch_models ( ) ) ;
continue ;
}
if ( ! strncmp ( line , " !model " , 6 ) ) {
if ( line [ 6 ] = = ' ' ) {
set_prompt_model ( line + 7 ) ;
}
printf ( " Current model: %s \n " , get_prompt_model ( ) ) ;
continue ;
}
if ( ! strncmp ( line , " exit " , 4 ) ) exit ( 0 ) ;
while ( line & & * line ! = ' \n ' ) {
char * response = openai_chat ( " user " , line ) ;
if ( response ) {
render ( response ) ;
printf ( " \n " ) ;
if ( strstr ( response , " _STEP_ " ) ) {
line = " continue " ;
} else {
line = NULL ;
}
free ( response ) ;
} else {
exit ( 0 ) ;
}
}
}
}
char * strreplace ( const char * content , const char * what , const char * with ) {
char * pos = strstr ( content , what ) ;
if ( ! pos ) return strdup ( content ) ;
size_t result_size = strlen ( content ) + strlen ( with ) - strlen ( what ) + 1 ;
char * result = malloc ( result_size ) ;
snprintf ( result , result_size , " %.*s%s%s " , ( int ) ( pos - content ) , content , with , pos + strlen ( what ) ) ;
return result ;
}
bool openai_include ( const char * path ) {
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 } ;
snprintf ( payload , sizeof ( 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 , " Loading... 4e6 " ) ;
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 + + ;
} else {
if ( difftime ( current_time , first_sigint_time ) < = 1 ) {
exit ( 0 ) ;
} else {
sigint_count = 1 ;
first_sigint_time = current_time ;
}
}
}
int main ( int argc , char * argv [ ] ) {
signal ( SIGINT , handle_sigint ) ;
init ( ) ;
if ( try_prompt ( argc , argv ) ) return 0 ;
repl ( ) ;
return 0 ;
}