mirror of
https://git.jabber.space/devs/cproof.git
synced 2026-07-19 06:56:21 +00:00
Merge branch 'test/ai-coverage-unit-only' into fix/ai-followups
Pull in the defaults-agnostic unit and functional test coverage so this branch carries both the source fixes and the tests that exercise them. # Conflicts: # src/ai/ai_client.c
This commit is contained in:
@@ -37,7 +37,6 @@ static void _ai_load_models_for_provider(AIProvider* provider);
|
||||
static void _ai_save_models_for_provider(AIProvider* provider);
|
||||
static const gchar* _find_json_field(const gchar* json, const gchar* field);
|
||||
static gchar* _extract_json_string(const gchar* json, const gchar* field);
|
||||
static gchar* _parse_error_response(const gchar* error_json);
|
||||
|
||||
/* ========================================================================
|
||||
* Curl helpers
|
||||
@@ -687,7 +686,7 @@ _curl_exec_and_handle(CURL* curl, const gchar* url, struct curl_slist* headers,
|
||||
log_error("Request failed for '%s': %s", provider->name, error_msg);
|
||||
_aiwin_display_error(user_data, error_msg);
|
||||
} else if (http_code >= 400) {
|
||||
auto_gchar gchar* parsed = _parse_error_response(response->data);
|
||||
auto_gchar gchar* parsed = ai_parse_error_message(response->data);
|
||||
auto_gchar gchar* error_msg = parsed
|
||||
? g_strdup_printf("HTTP %ld: %s", http_code, parsed)
|
||||
: g_strdup_printf("HTTP %ld: %s", http_code,
|
||||
@@ -1340,8 +1339,8 @@ _build_json_payload_from_list(const gchar* model, GList* history, const gchar* p
|
||||
return json_payload;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
_parse_ai_response(const gchar* response_json)
|
||||
gchar*
|
||||
ai_parse_response(const gchar* response_json)
|
||||
{
|
||||
if (!response_json || strlen(response_json) == 0)
|
||||
return NULL;
|
||||
@@ -1359,8 +1358,8 @@ _parse_ai_response(const gchar* response_json)
|
||||
* {"error":{"message":"...","type":"...","code":...}}
|
||||
* Scoped to the substring after "error": so unrelated top-level "message"
|
||||
* fields do not get picked up. */
|
||||
static gchar*
|
||||
_parse_error_response(const gchar* error_json)
|
||||
gchar*
|
||||
ai_parse_error_message(const gchar* error_json)
|
||||
{
|
||||
if (!error_json || strlen(error_json) == 0)
|
||||
return NULL;
|
||||
@@ -1477,7 +1476,7 @@ _ai_request_thread(gpointer data)
|
||||
log_debug("[AI-THREAD] HTTP error response body (%zu bytes): %s",
|
||||
response.size, response.data ? response.data : "NULL");
|
||||
/* Try to extract the actual error message from the JSON response */
|
||||
auto_gchar gchar* parsed_error = _parse_error_response(response.data);
|
||||
auto_gchar gchar* parsed_error = ai_parse_error_message(response.data);
|
||||
auto_gchar gchar* error_msg = parsed_error ? g_strdup_printf("HTTP %ld: %s", http_code, parsed_error) : g_strdup_printf("HTTP %ld: %s", http_code, response.data && strlen(response.data) > 0 ? response.data : "Unknown error");
|
||||
log_error("AI request failed for %s/%s: %s", local_provider_name, local_model, error_msg);
|
||||
_aiwin_display_error(user_data, error_msg);
|
||||
@@ -1486,7 +1485,7 @@ _ai_request_thread(gpointer data)
|
||||
log_debug("[AI-THREAD] Raw API response (%zu bytes): %s", response.size, response.data ? response.data : "NULL");
|
||||
auto_gchar gchar* response_data = response.data;
|
||||
response.data = NULL;
|
||||
auto_gchar gchar* content = _parse_ai_response(response_data);
|
||||
auto_gchar gchar* content = ai_parse_response(response_data);
|
||||
if (content) {
|
||||
/* Add assistant response to history (under lock) */
|
||||
pthread_mutex_lock(&session->lock);
|
||||
|
||||
@@ -172,7 +172,7 @@ gboolean ai_fetch_models(const gchar* provider_name, gpointer user_data);
|
||||
gboolean ai_models_are_fresh(const gchar* provider_name);
|
||||
|
||||
/* ========================================================================
|
||||
* Model Parsing (for testing)
|
||||
* Parsing helpers (exposed for testing)
|
||||
* ======================================================================== */
|
||||
|
||||
/**
|
||||
@@ -183,6 +183,24 @@ gboolean ai_models_are_fresh(const gchar* provider_name);
|
||||
*/
|
||||
void ai_parse_models_from_json(AIProvider* provider, const gchar* json);
|
||||
|
||||
/**
|
||||
* Extract assistant content from an LLM response body. Tries Perplexity
|
||||
* /v1/responses "text" first, falls back to OpenAI "content". Decodes
|
||||
* the \" and \n escape sequences only.
|
||||
* @param response_json The JSON body from the provider
|
||||
* @return Newly allocated content string, or NULL if not found (caller frees)
|
||||
*/
|
||||
gchar* ai_parse_response(const gchar* response_json);
|
||||
|
||||
/**
|
||||
* Extract human-readable error message from an API error envelope.
|
||||
* Expected format: {"error":{"message":"...","type":"...","code":...}}
|
||||
* Decodes \" \n \\ \t escapes.
|
||||
* @param error_json The JSON body of the error response
|
||||
* @return Newly allocated error message, or NULL if not parseable (caller frees)
|
||||
*/
|
||||
gchar* ai_parse_error_message(const gchar* error_json);
|
||||
|
||||
/* ========================================================================
|
||||
* Session Management
|
||||
* ======================================================================== */
|
||||
|
||||
Reference in New Issue
Block a user