refactor(ai): add UI display helpers
Some checks failed
CI Code / Check spelling (pull_request) Successful in 54s
CI Code / Check coding style (pull_request) Successful in 2m4s
CI Code / Linux (debian) (pull_request) Failing after 2m56s
CI Code / Linux (arch) (pull_request) Failing after 3m10s
CI Code / Linux (ubuntu) (pull_request) Failing after 3m9s
CI Code / Code Coverage (pull_request) Successful in 2m55s

Add static _aiwin_display_error() and
_aiwin_display_response() helpers to reduce mutex repetition and
log warnings when aiwin is NULL or invalid.
This commit is contained in:
2026-05-01 16:36:07 +00:00
parent cead417e78
commit fe0a46da58

View File

@@ -67,6 +67,44 @@ _write_callback(void* ptr, size_t size, size_t nmemb, void* userdata)
return realsize;
}
/* ========================================================================
* Thread-safe UI display helpers
* ======================================================================== */
/**
* Display an error message in the AI window (thread-safe).
* @param aiwin The AI window (may be NULL)
* @param error_msg The error message to display
*/
static void
_aiwin_display_error(ProfAiWin* aiwin, const gchar* error_msg)
{
if (!aiwin || aiwin->memcheck != PROFAIWIN_MEMCHECK) {
log_warning("[AI-THREAD] Cannot display error: aiwin is NULL or invalid (msg: %s)", error_msg);
return;
}
pthread_mutex_lock(&lock);
aiwin_display_error(aiwin, error_msg);
pthread_mutex_unlock(&lock);
}
/**
* Display a response message in the AI window (thread-safe).
* @param aiwin The AI window (may be NULL)
* @param response The response message to display
*/
static void
_aiwin_display_response(ProfAiWin* aiwin, const gchar* response)
{
if (!aiwin || aiwin->memcheck != PROFAIWIN_MEMCHECK) {
log_warning("[AI-THREAD] Cannot display response: aiwin is NULL or invalid");
return;
}
pthread_mutex_lock(&lock);
aiwin_display_response(aiwin, response);
pthread_mutex_unlock(&lock);
}
/* ========================================================================
* JSON helpers
* ======================================================================== */
@@ -615,15 +653,7 @@ _ai_request_thread(gpointer data)
auto_gchar gchar* error_msg = g_strdup_printf("No API key set for provider '%s'. Use '/ai set token %s <key>' to configure.",
session->provider_name, session->provider_name);
log_error("AI request failed for %s/%s: %s", session->provider_name, session->model, error_msg);
/* Display error directly in AI window */
pthread_mutex_lock(&lock);
ProfAiWin* aiwin = (ProfAiWin*)user_data;
if (aiwin && aiwin->memcheck == PROFAIWIN_MEMCHECK) {
aiwin_display_error(aiwin, error_msg);
}
pthread_mutex_unlock(&lock);
_aiwin_display_error((ProfAiWin*)user_data, error_msg);
g_free(args);
return NULL;
}
@@ -633,15 +663,7 @@ _ai_request_thread(gpointer data)
if (!curl) {
log_error("AI request failed for %s/%s: Failed to initialize curl",
session->provider_name, session->model);
/* Display error directly in AI window */
pthread_mutex_lock(&lock);
ProfAiWin* aiwin = (ProfAiWin*)user_data;
if (aiwin && aiwin->memcheck == PROFAIWIN_MEMCHECK) {
aiwin_display_error(aiwin, "Failed to initialize curl.");
}
pthread_mutex_unlock(&lock);
_aiwin_display_error((ProfAiWin*)user_data, "Failed to initialize curl.");
g_free(args);
return NULL;
}
@@ -696,14 +718,7 @@ _ai_request_thread(gpointer data)
if (res != CURLE_OK) {
auto_gchar gchar* error_msg = g_strdup(curl_easy_strerror(res));
log_error("AI request failed for %s/%s: %s", session->provider_name, session->model, error_msg);
/* Display error directly in AI window */
pthread_mutex_lock(&lock);
ProfAiWin* aiwin = (ProfAiWin*)user_data;
if (aiwin && aiwin->memcheck == PROFAIWIN_MEMCHECK) {
aiwin_display_error(aiwin, error_msg);
}
pthread_mutex_unlock(&lock);
_aiwin_display_error((ProfAiWin*)user_data, error_msg);
} else if (http_code >= 400) {
/* Handle HTTP errors */
log_debug("[AI-THREAD] HTTP error response body (%zu bytes): %s",
@@ -711,14 +726,7 @@ _ai_request_thread(gpointer data)
auto_gchar gchar* error_msg = g_strdup_printf("HTTP %ld: %s", http_code,
response.data ? response.data : "Unknown error");
log_error("AI request failed for %s/%s: %s", session->provider_name, session->model, error_msg);
/* Display error directly in AI window */
pthread_mutex_lock(&lock);
ProfAiWin* aiwin = (ProfAiWin*)user_data;
if (aiwin && aiwin->memcheck == PROFAIWIN_MEMCHECK) {
aiwin_display_error(aiwin, error_msg);
}
pthread_mutex_unlock(&lock);
_aiwin_display_error((ProfAiWin*)user_data, error_msg);
} else {
/* Parse response - transfer ownership to auto_gchar for cleanup */
log_debug("[AI-THREAD] Raw API response (%zu bytes): %s", response.size, response.data ? response.data : "NULL");
@@ -728,25 +736,11 @@ _ai_request_thread(gpointer data)
if (content) {
/* Add assistant response to history */
ai_session_add_message(session, "assistant", content);
/* Display response directly in AI window */
pthread_mutex_lock(&lock);
ProfAiWin* aiwin = (ProfAiWin*)user_data;
if (aiwin && aiwin->memcheck == PROFAIWIN_MEMCHECK) {
aiwin_display_response(aiwin, content);
}
pthread_mutex_unlock(&lock);
_aiwin_display_response((ProfAiWin*)user_data, content);
} else {
log_error("AI response parse failed for %s/%s: %.200s...",
session->provider_name, session->model, response_data);
/* Display parse error directly in AI window */
pthread_mutex_lock(&lock);
ProfAiWin* aiwin = (ProfAiWin*)user_data;
if (aiwin && aiwin->memcheck == PROFAIWIN_MEMCHECK) {
aiwin_display_error(aiwin, "Failed to parse AI response.");
}
pthread_mutex_unlock(&lock);
_aiwin_display_error((ProfAiWin*)user_data, "Failed to parse AI response.");
}
}