From 42723a29fd036268ac65bc131cff70f17113d0b9 Mon Sep 17 00:00:00 2001 From: Jivaansh Yadav Date: Sat, 13 Jun 2026 19:00:21 +0530 Subject: [PATCH 1/2] Added '[DEPRECATED]' tag to deprecated Gemini Models These models have officially lost support as of 13-06-2026. ``` models/gemini-2.0-flash models/gemini-2.0-flash-001 models/gemini-2.0-flash-lite models/gemini-2.0-flash-lite-001 models/gemini-3-pro-preview models/gemini-3.1-flash-lite-preview ``` These models will now be listed as [DEPRECATED] in the models list but will be usable in the terminal. *On branch deprecated-gemini-models Changes to be committed: - modified: ai.py* --- ai.py | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/ai.py b/ai.py index 140aa77..80d5104 100644 --- a/ai.py +++ b/ai.py @@ -380,11 +380,11 @@ def _render_line_impl(self, line: str, in_code_block: bool) -> tuple[str, bool]: if stripped.startswith("```"): new_state = not in_code_block lang = stripped[3:].strip() - + # Use dynamic cached width to respect terminal resizes term_cols = _get_term_cols() bar_len = min(term_cols - 4, 60) - + if new_state: # Opening a code block lbl = lang.upper() or 'CODE' dashes = max(1, bar_len - 17 - len(lbl)) @@ -460,6 +460,29 @@ def preview_line(self, line: str) -> str: VALID_PROVIDERS = list(ENDPOINTS.keys()) +# Deprecated Gemini models (as of June 1, 2026) +DEPRECATED_GEMINI_MODELS = ( + "gemini-2.0-flash", + "gemini-2.0-flash-001", + "gemini-2.0-flash-lite", + "gemini-2.0-flash-lite-001", + "gemini-3-pro-preview", + "gemini-3.1-flash-lite-preview", +) + +def _is_model_deprecated(model_name: str, provider: str) -> bool: + if provider != "gemini": + return False + return model_name.lower() in [m.lower() for m in DEPRECATED_GEMINI_MODELS] + +def _mark_deprecated_models(models: list[str], provider: str) -> list[str]: + if provider != "gemini": + return models + return [ + f"{m} {C.ERROR}[DEPRECATED]{C.RESET}" if _is_model_deprecated(m, provider) else m + for m in models + ] + # ───────────────────────────────────────────────────────────────────────────── # HELPERS @@ -495,7 +518,7 @@ def check_placeholder_key(key: str, provider: str) -> bool: bad = "looks incomplete" elif provider == "cloudflare" and ":" not in key: bad = "is missing the Account ID (Format must be ACCOUNT_ID:API_TOKEN)" - + if bad: eprint(f"{C.WARN}WARNING: API key for {provider.upper()} {bad}.{C.RESET}") return False @@ -826,7 +849,7 @@ def _fetch_page(url: str, timeout: int = 20) -> str: cl_int = int(cl) except ValueError: cl_int = 0 - + if cl_int > FETCH_MAX_BYTES: raise RuntimeError(f"Response too large: {cl_int} bytes") raw = resp.read(FETCH_MAX_BYTES + 1) @@ -1480,7 +1503,7 @@ def _eval_node(node: ast.AST) -> Any: # Only replace ^ if it's not being used as a valid Python BitXor operator if "^" in expression and "**" not in expression: expression = expression.replace("^", "**") - + tree = ast.parse(expression, mode="eval") result = _eval_node(tree.body) if isinstance(result, float) and result == int(result) and not math.isinf(result): @@ -2034,7 +2057,9 @@ def fetch_models(provider: str, api_key: str) -> Optional[list[str]]: eprint(f"{C.ERROR}Could not parse model list: {exc}{C.RESET}") return None - return[m for m in models if m] + models = [m for m in models if m] + models = _mark_deprecated_models(models, provider) + return models _PICK_SEL_BG = "\033[48;5;215m" @@ -2217,16 +2242,16 @@ def _interactive_confirm(prompt: str, default: bool = True, color: str = C.INFO) selected = default _stdout_write("\033[?25l") # Hide cursor safely - + try: with _RawTerminal(): while True: yes_str = f"{_PICK_SEL_BG}{_PICK_SEL_FG} Yes {C.RESET}" if selected else " Yes " no_str = f"{_PICK_SEL_BG}{_PICK_SEL_FG} No {C.RESET}" if not selected else " No " - + # Write inline prompt _stdout_write(f"\r{C.CLR}{color}✦ {prompt}{C.RESET} {yes_str} {no_str}") - + key = _read_picker_key() if key in ("LEFT", "UP", "RIGHT", "DOWN", "h", "l", "j", "k"): selected = not selected @@ -2240,11 +2265,11 @@ def _interactive_confirm(prompt: str, default: bool = True, color: str = C.INFO) break elif key == "ESC": sys.exit(0) - + ans_str = "Yes" if selected else "No" _stdout_write(f"\r{C.CLR}{color}✓ {prompt}{C.RESET} {C.BOLD}{ans_str}{C.RESET}\n") return selected - + except KeyboardInterrupt: _stdout_write("\r") sys.exit(0) @@ -2279,7 +2304,7 @@ def _render_provider_picker(providers: list[str], selected: int) -> None: "novita": "Novita", "ollama": "Ollama" }.get(p, p.title()) - + row = f" {num}. {display_name}" if idx == selected: lines.append(f"│{_PICK_SEL_BG}{_PICK_SEL_FG}{_ansi_pad(row, inner_width)}{C.RESET}│") @@ -2882,7 +2907,7 @@ def feed_thinking(self, think_tok: str) -> None: if not self._in_think_display: _stdout_write(f"{C.THINK}[Thinking]\n┃ {C.RESET}{C.THINK}") self._in_think_display = True - + indented_think = think_tok.replace("\n", f"\n{C.THINK}┃ {C.RESET}{C.THINK}") _stdout_write(f"{C.THINK}{indented_think}{C.RESET}") From 930bb3a416921315decc5bd3baa806345434ae7a Mon Sep 17 00:00:00 2001 From: Jivaansh Yadav Date: Sat, 13 Jun 2026 19:26:14 +0530 Subject: [PATCH 2/2] Added '[DEPRECATED]' tag to deprecated Gemini Models These models have officially lost support as of 13-06-2026. ``` models/gemini-2.0-flash models/gemini-2.0-flash-001 models/gemini-2.0-flash-lite models/gemini-2.0-flash-lite-001 models/gemini-3-pro-preview models/gemini-3.1-flash-lite-preview ``` These models will now be listed as [DEPRECATED] in the models list but will be usable in the terminal. *On branch deprecated-gemini-models Changes to be committed: `modified: ai.sh`* --- ai.sh | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/ai.sh b/ai.sh index 5134674..e043f52 100644 --- a/ai.sh +++ b/ai.sh @@ -320,6 +320,46 @@ regex_escape_ere() { printf '%s' "$1" | sed -e 's/[][(){}.^$*+?|\\]/\\&/g' } +# Deprecated Gemini models (as of June 1, 2026) +DEPRECATED_GEMINI_MODELS=( + "gemini-2.0-flash" + "gemini-2.0-flash-001" + "gemini-2.0-flash-lite" + "gemini-2.0-flash-lite-001" + "gemini-3-pro-preview" + "gemini-3.1-flash-lite-preview" +) + +is_model_deprecated() { + local model="$1" + local provider="$2" + + if [[ "$provider" != "gemini" ]]; then + return 1 + fi + + local model_lower + model_lower="$(printf '%s' "$model" | tr '[:upper:]' '[:lower:]')" + + for deprecated in "${DEPRECATED_GEMINI_MODELS[@]}"; do + if [[ "$model_lower" == "$deprecated" ]]; then + return 0 + fi + done + return 1 +} + +model_display_name() { + local model="$1" + local provider="$2" + + if is_model_deprecated "$model" "$provider"; then + printf '%s %s[DEPRECATED]%s' "$model" "$COLOR_ERROR" "$COLOR_RESET" + else + printf '%s' "$model" + fi +} + # --- Image Helper Functions --- validate_image_file() { local file_path="$1" @@ -589,11 +629,11 @@ MODEL_ID="" # --- Auto-select if only one model, otherwise prompt user --- if [ ${#available_models[@]} -eq 1 ]; then MODEL_ID="${available_models[0]}" - echo -e "${COLOR_INFO}Auto-selecting only matching model.${COLOR_RESET}" + echo -e "${COLOR_INFO}Auto-selecting only matching model:${COLOR_RESET} $(model_display_name "$MODEL_ID" "$PROVIDER")" else echo -e "${COLOR_INFO}Available Models for ${PROVIDER^^}:${COLOR_RESET}" for i in "${!available_models[@]}"; do - printf " ${COLOR_BOLD}%3d${COLOR_RESET}. %s\n" $((i+1)) "${available_models[$i]}" + printf " ${COLOR_BOLD}%3d${COLOR_RESET}. %s\n" $((i+1)) "$(model_display_name "${available_models[$i]}" "$PROVIDER")" done echo "" while true; do @@ -607,7 +647,7 @@ else done fi -echo -e "${COLOR_INFO}Using model:${COLOR_RESET} ${MODEL_ID}" +echo -e "${COLOR_INFO}Using model:${COLOR_RESET} $(model_display_name "$MODEL_ID" "$PROVIDER")" echo "" CHAT_API_URL=""