fix: ai — per-provider API keys (remove shared AI_API_KEY)
gates / consistency-and-conventions (push) Failing after 11s

Each provider now has its own key: AI_GEMINI_API_KEY and OPENROUTER_API_KEY.
No more shared AI_API_KEY that caused cross-provider key leakage (gemini
getting openrouter key → 400 error). resolve_key() sets AI_API_KEY internally
from the active provider's key for adapter use. Config UI shows both keys.
This commit is contained in:
Your Name
2026-08-26 02:36:48 -04:00
parent 88ea660891
commit 7ae2e77a44
2 changed files with 23 additions and 31 deletions
+11 -22
View File
@@ -3,7 +3,7 @@ set -euo pipefail
# POS: ai ask — AI assistant: ask, chat, sessions, capture, models, providers
# POS_SUBCMDS: ask chat sessions capture models providers
# POS_FLAGS: --provider --model --session --system --full --last
# POS_CONFIG: ai | ai.env | AI_PROVIDER=:Provider (gemini or openrouter, default gemini) | AI_API_KEY=secret:API key for the active provider | AI_MODEL=:Model id (default per provider) | AI_SYSTEM_PROMPT=:Custom system prompt (overrides built-in, empty to reset)
# POS_CONFIG: ai | ai.env | AI_PROVIDER=:Provider (gemini or openrouter, default gemini) | AI_GEMINI_API_KEY=secret:Gemini API key from aistudio.google.com | OPENROUTER_API_KEY=secret:OpenRouter API key from openrouter.ai | AI_MODEL=:Model id (default per provider) | AI_SYSTEM_PROMPT=:Custom system prompt (overrides built-in, empty to reset)
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
@@ -76,12 +76,10 @@ Options:
Config: $CONFIG_FILE (edit with 'pos config ai')
AI_PROVIDER Provider to use (gemini|openrouter, default gemini)
AI_API_KEY API key for the active provider (secret)
AI_GEMINI_API_KEY Gemini API key from aistudio.google.com
OPENROUTER_API_KEY OpenRouter API key from openrouter.ai
AI_MODEL Model id (default depends on provider)
AI_SYSTEM_PROMPT Custom system prompt (overrides built-in; empty to reset)
AI_GEMINI_API_KEY Legacy: Gemini API key fallback
AI_GEMINI_MODEL Legacy: Gemini model fallback
OPENROUTER_API_KEY Legacy: OpenRouter API key fallback
OPENROUTER_MODEL Legacy: OpenRouter model fallback
Notes:
@@ -164,16 +162,11 @@ load_config() {
resolve_key() {
load_config
local p="${PROVIDER:-gemini}"
# 1. Unified AI_API_KEY
if [ -n "${AI_API_KEY:-}" ]; then
return 0
fi
# 2. Provider-specific fallback
# Each provider has its own API key — set AI_API_KEY internally for adapters
case "$p" in
gemini) [ -n "${AI_GEMINI_API_KEY:-}" ] && export AI_API_KEY="$AI_GEMINI_API_KEY" && return 0 ;;
openrouter) [ -n "${OPENROUTER_API_KEY:-}" ] && export AI_API_KEY="$OPENROUTER_API_KEY" && return 0 ;;
esac
# 3. No key found — return 1 (require_key handles the error message)
return 1
}
@@ -181,10 +174,10 @@ require_key() {
if ! resolve_key >/dev/null 2>&1; then
local p="${PROVIDER:-gemini}"
case "$p" in
gemini) err "No Gemini API key — run 'pos config ai' or set AI_API_KEY / AI_GEMINI_API_KEY" ;;
openrouter) err "No OpenRouter API key — run 'pos config ai' or set AI_API_KEY / OPENROUTER_API_KEY" ;;
gemini) err "No Gemini API key — run 'pos config ai' and set AI_GEMINI_API_KEY" ;;
openrouter) err "No OpenRouter API key — run 'pos config ai' and set OPENROUTER_API_KEY" ;;
esac
err "No API key for provider '$p' — run 'pos config ai' or set AI_API_KEY"
err "No API key for provider '$p' — run 'pos config ai'"
fi
}
@@ -569,14 +562,10 @@ cmd_providers() {
[ -n "$pmodel" ] || pmodel="unknown"
# Check if API key exists for this provider
configured="not configured"
if [ -n "${AI_API_KEY:-}" ]; then
configured="configured"
else
case "$name" in
gemini) [ -n "${AI_GEMINI_API_KEY:-}" ] && configured="configured" ;;
openrouter) [ -n "${OPENROUTER_API_KEY:-}" ] && configured="configured" ;;
esac
fi
case "$name" in
gemini) [ -n "${AI_GEMINI_API_KEY:-}" ] && configured="configured" ;;
openrouter) [ -n "${OPENROUTER_API_KEY:-}" ] && configured="configured" ;;
esac
current=""
[ "$name" = "$active" ] && current=" ← active"
printf ' %-16s %s (model: %s)%s\n' "$name" "$configured" "$pmodel" "$current"
+12 -9
View File
@@ -2,14 +2,17 @@
# Copied to ~/.config/linux_post_install/ai.env on install (no clobber).
# Edit with: pos config ai
#
# Syntax:
# Provider selection:
# AI_PROVIDER=gemini # provider: gemini|openrouter (default gemini)
# AI_API_KEY=<key> # API key for the active provider (secret)
# AI_MODEL=<model> # model id (default depends on provider)
# AI_SYSTEM_PROMPT=<prompt> # custom system prompt (overrides built-in; empty to reset)
#
# Legacy provider-specific keys (still supported as fallback):
# AI_GEMINI_API_KEY=<key> # Gemini API key (used when AI_API_KEY is empty)
# AI_GEMINI_MODEL=<model> # Gemini model id (used when AI_MODEL is empty)
# OPENROUTER_API_KEY=<key> # OpenRouter API key (used when AI_API_KEY is empty)
# OPENROUTER_MODEL=<model> # OpenRouter model id (used when AI_MODEL is empty)
# API keys (each provider needs its own):
# AI_GEMINI_API_KEY=<key> # Gemini API key from aistudio.google.com
# OPENROUTER_API_KEY=<key> # OpenRouter API key from openrouter.ai
#
# Model overrides (optional, defaults per provider):
# AI_GEMINI_MODEL=<model> # Gemini model id (default: gemini-2.5-flash)
# OPENROUTER_MODEL=<model> # OpenRouter model id (default: openrouter/auto)
# AI_MODEL=<model> # Override for all providers (takes priority)
#
# System prompt:
# AI_SYSTEM_PROMPT=<prompt> # Custom system prompt (overrides built-in; empty to reset)