diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index bda8b79a..234083f5 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -70,7 +70,6 @@ static char* _sub_autocomplete(ProfWin* window, const char* const input, gboolean previous); static char* _notify_autocomplete(ProfWin* window, const char* const input, gboolean previous); -static char* _ai_model_autocomplete(ProfWin* window, const char* const input, gboolean previous, const char* prefix); static char* _theme_autocomplete(ProfWin* window, const char* const input, gboolean previous); static char* _autoaway_autocomplete(ProfWin* window, const char* const input, gboolean previous); static char* _autoconnect_autocomplete(ProfWin* window, const char* const input, gboolean previous); @@ -4488,6 +4487,10 @@ _force_encryption_autocomplete(ProfWin* window, const char* const input, gboolea return result; } +/* Forward declaration */ +static char* _ai_provider_and_model_autocomplete(ProfWin* window, const char* const input, + gboolean previous, const char* cmd); + static char* _ai_autocomplete(ProfWin* window, const char* const input, gboolean previous) { @@ -4496,7 +4499,6 @@ _ai_autocomplete(ProfWin* window, const char* const input, gboolean previous) /* Parse once for reuse - /ai [] [] */ gboolean parse_result = FALSE; auto_gcharv gchar** args = parse_args(input, 1, 4, &parse_result); - gboolean space_at_end = g_str_has_suffix(input, " "); int num_args = g_strv_length(args); /* Top-level /ai autocomplete (e.g., /ai s -> /ai set) */ @@ -4552,27 +4554,20 @@ _ai_autocomplete(ProfWin* window, const char* const input, gboolean previous) return result; } - // /ai start [] [] - use shared parse_args - if (parse_result && args && args[0] != NULL && g_strcmp0(args[0], "start") == 0) { - /* args[0]="start", args[1]=provider (if typed), args[2]=model (if typed) */ - if (num_args == 1 || (num_args == 2 && !space_at_end)) { - result = autocomplete_param_with_func(input, "/ai start", ai_providers_find, previous, NULL); - } else { - /* /ai start - model autocomplete */ - result = _ai_model_autocomplete(window, input, previous, "/ai start "); - } - if (result) { - return result; - } - } - - // /ai switch - autocomplete model names for specified provider - result = _ai_model_autocomplete(window, input, previous, "/ai switch "); + // /ai start - autocomplete provider names and model names + result = _ai_provider_and_model_autocomplete(window, input, previous, "/ai start"); if (result) { return result; } - result = autocomplete_param_with_func(input, "/ai switch", ai_providers_find, previous, NULL); + // /ai switch - autocomplete provider names and model names + result = _ai_provider_and_model_autocomplete(window, input, previous, "/ai switch"); + if (result) { + return result; + } + + // /ai set default-model - autocomplete provider names and model names + result = _ai_provider_and_model_autocomplete(window, input, previous, "/ai set default-model"); if (result) { return result; } @@ -4592,13 +4587,26 @@ _ai_autocomplete(ProfWin* window, const char* const input, gboolean previous) } /** - * Autocomplete model names for /ai patterns. - * Extracts provider from input and provides model completions from that provider's cached models. + * Autocomplete provider names and model names for /ai patterns. + * First tries to autocomplete provider names, then model names if provider is valid. * Uses static ai_models_ac to preserve cycling state (last_found) across calls. + * The cmd_prefix should NOT include trailing space (e.g., "/ai start" not "/ai start "). */ static char* -_ai_model_autocomplete(ProfWin* window, const char* const input, gboolean previous, const char* cmd_prefix) +_ai_provider_and_model_autocomplete(ProfWin* window, const char* const input, gboolean previous, const char* cmd) { + char* result; + + /* First, try provider name autocomplete */ + result = autocomplete_param_with_func(input, cmd, ai_providers_find, previous, NULL); + if (result) { + return result; + } + + /* Provider was specified, try model name autocomplete */ + /* Build the full command prefix with space */ + auto_gchar gchar* cmd_prefix = g_strdup_printf("%s ", cmd); + if (!g_str_has_prefix(input, cmd_prefix)) { return NULL; } @@ -4634,6 +4642,6 @@ _ai_model_autocomplete(ProfWin* window, const char* const input, gboolean previo auto_gchar gchar* full_prefix = g_strdup_printf("%s%s", cmd_prefix, rest); - char* result = autocomplete_param_with_ac(input, full_prefix, ai_models_ac, TRUE, previous); + result = autocomplete_param_with_ac(input, full_prefix, ai_models_ac, TRUE, previous); return result; } diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c index b7fb00b3..84fa9e16 100644 --- a/src/tools/autocomplete.c +++ b/src/tools/autocomplete.c @@ -305,7 +305,7 @@ autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean quote, // autocomplete_func func is used -> autocomplete_param_with_func // Autocomplete ac, gboolean quote are used -> autocomplete_param_with_ac static char* -_autocomplete_param_common(const char* const input, char* command, autocomplete_func func, Autocomplete ac, gboolean quote, gboolean previous, void* context) +_autocomplete_param_common(const char* const input, const char* command, autocomplete_func func, Autocomplete ac, gboolean quote, gboolean previous, void* context) { int len; auto_gchar gchar* command_cpy = g_strdup_printf("%s ", command); @@ -344,7 +344,7 @@ _autocomplete_param_common(const char* const input, char* command, autocomplete_ } char* -autocomplete_param_with_func(const char* const input, char* command, autocomplete_func func, gboolean previous, void* context) +autocomplete_param_with_func(const char* const input, const char* command, autocomplete_func func, gboolean previous, void* context) { return _autocomplete_param_common(input, command, func, NULL, FALSE, previous, context); } diff --git a/src/tools/autocomplete.h b/src/tools/autocomplete.h index 851dbc0d..4a62de4c 100644 --- a/src/tools/autocomplete.h +++ b/src/tools/autocomplete.h @@ -63,7 +63,7 @@ gchar* autocomplete_complete(Autocomplete ac, const gchar* search_str, gboolean GList* autocomplete_create_list(Autocomplete ac); gint autocomplete_length(Autocomplete ac); -char* autocomplete_param_with_func(const char* const input, char* command, +char* autocomplete_param_with_func(const char* const input, const char* command, autocomplete_func func, gboolean previous, void* context); char* autocomplete_param_with_ac(const char* const input, char* command,