// retoor #include "r_config.h" #include #include #include #include struct r_config_t { char *api_url; char *models_url; char *model; char *api_key; char *db_path; char *session_id; char *system_message; double temperature; int max_tokens; bool use_tools; bool use_strict; bool verbose; }; static struct r_config_t *instance = NULL; static char *strdup_safe(const char *s) { return s ? strdup(s) : NULL; } static bool resolve_env_bool(const char *env_name, bool default_val) { const char *val = getenv(env_name); if (!val) return default_val; if (!strcmp(val, "true") || !strcmp(val, "1")) return true; if (!strcmp(val, "false") || !strcmp(val, "0")) return false; return default_val; } static const char *resolve_api_key(void) { const char * key = getenv("R_KEY"); if (key && *key) return key; key = getenv("OPENROUTER_API_KEY"); if (key && *key) return key; key = getenv("OPENAI_API_KEY"); if (key && *key) return key; return "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"; } static bool is_valid_session_id(const char *session_id) { if (!session_id || !*session_id) return false; if (strlen(session_id) > 255) return false; for (const char *p = session_id; *p; p++) { if (!isalnum((unsigned char)*p) && *p != '-' && *p != '_' && *p != '.') { return false; } } return true; } r_config_handle r_config_get_instance(void) { if (instance) return instance; instance = calloc(1, sizeof(struct r_config_t)); if (!instance) return NULL; const char *base_url = getenv("R_BASE_URL"); if (base_url && *base_url) { size_t len = strlen(base_url); instance->api_url = malloc(len + 32); instance->models_url = malloc(len + 32); if (instance->api_url && instance->models_url) { snprintf(instance->api_url, len + 32, "%s/v1/chat/completions", base_url); snprintf(instance->models_url, len + 32, "%s/v1/models", base_url); } } else { instance->api_url = strdup("https://api.openai.com/v1/chat/completions"); instance->models_url = strdup("https://api.openai.com/v1/models"); } const char *model = getenv("R_MODEL"); instance->model = strdup(model && *model ? model : "gpt-4o-mini"); instance->api_key = strdup(resolve_api_key()); instance->db_path = strdup("~/.r.db"); instance->temperature = 0.1; const char *max_tokens_env = getenv("R_MAX_TOKENS"); instance->max_tokens = max_tokens_env ? atoi(max_tokens_env) : 4096; instance->use_tools = resolve_env_bool("R_USE_TOOLS", true); instance->use_strict = resolve_env_bool("R_USE_STRICT", true); instance->verbose = false; const char *session = getenv("R_SESSION"); if (session && is_valid_session_id(session)) { instance->session_id = strdup(session); } else { instance->session_id = NULL; } instance->system_message = strdup_safe(getenv("R_SYSTEM_MESSAGE")); return instance; } void r_config_destroy(void) { if (!instance) return; free(instance->api_url); free(instance->models_url); free(instance->model); free(instance->api_key); free(instance->db_path); free(instance->session_id); free(instance->system_message); free(instance); instance = NULL; } const char *r_config_get_api_url(r_config_handle cfg) { return cfg ? cfg->api_url : NULL; } const char *r_config_get_models_url(r_config_handle cfg) { return cfg ? cfg->models_url : NULL; } const char *r_config_get_model(r_config_handle cfg) { return cfg ? cfg->model : NULL; } void r_config_set_model(r_config_handle cfg, const char *model) { if (!cfg || !model) return; free(cfg->model); cfg->model = strdup(model); } const char *r_config_get_api_key(r_config_handle cfg) { return cfg ? cfg->api_key : NULL; } const char *r_config_get_db_path(r_config_handle cfg) { return cfg ? cfg->db_path : NULL; } bool r_config_use_tools(r_config_handle cfg) { return cfg ? cfg->use_tools : true; } bool r_config_use_strict(r_config_handle cfg) { return cfg ? cfg->use_strict : true; } bool r_config_is_verbose(r_config_handle cfg) { return cfg ? cfg->verbose : false; } void r_config_set_verbose(r_config_handle cfg, bool verbose) { if (cfg) cfg->verbose = verbose; } double r_config_get_temperature(r_config_handle cfg) { return cfg ? cfg->temperature : 0.1; } int r_config_get_max_tokens(r_config_handle cfg) { return cfg ? cfg->max_tokens : 4096; } const char *r_config_get_session_id(r_config_handle cfg) { return cfg ? cfg->session_id : NULL; } bool r_config_set_session_id(r_config_handle cfg, const char *session_id) { if (!cfg || !is_valid_session_id(session_id)) return false; free(cfg->session_id); cfg->session_id = strdup(session_id); return cfg->session_id != NULL; } const char *r_config_get_system_message(r_config_handle cfg) { return cfg ? cfg->system_message : NULL; }