Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions lib/ai-gateway.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/bin/bash
# Optional WP AI Gateway integration for OpenCode runtimes.

AI_GATEWAY_PROVIDER_ID="wp-ai-gateway"
AI_GATEWAY_PROVIDER_ID="${AI_GATEWAY_PROVIDER_ID:-wp-ai-gateway}"
AI_GATEWAY_MODEL_ID="${AI_GATEWAY_MODEL_ID:-site-default}"
AI_GATEWAY_API_MODEL_ID="${AI_GATEWAY_API_MODEL_ID:-}"
AI_GATEWAY_ROUTE_PROVIDER="${AI_GATEWAY_ROUTE_PROVIDER:-openai}"
AI_GATEWAY_ROUTE_MODEL="${AI_GATEWAY_ROUTE_MODEL:-gpt-4o-mini}"
AI_GATEWAY_ENV_FILE="${AI_GATEWAY_ENV_FILE:-}"
Expand Down Expand Up @@ -59,6 +60,10 @@ ai_gateway_base_url() {
printf '%s/wp-json/wp-ai-gateway/v1' "${site_url%/}"
}

ai_gateway_api_model_id() {
printf '%s' "${AI_GATEWAY_API_MODEL_ID:-$AI_GATEWAY_MODEL_ID}"
}

ai_gateway_env_file() {
if [ -n "$AI_GATEWAY_ENV_FILE" ]; then
printf '%s' "$AI_GATEWAY_ENV_FILE"
Expand Down Expand Up @@ -147,14 +152,15 @@ ai_gateway_write_env() {
ai_gateway_configure_opencode() {
ai_gateway_enabled_for_opencode || return 0

local config_file env_file base_url
local config_file env_file base_url api_model_id
config_file="$SITE_PATH/opencode.json"
env_file="$(ai_gateway_env_file)"
base_url="$(ai_gateway_base_url)"
api_model_id="$(ai_gateway_api_model_id)"

if [ "$DRY_RUN" = true ]; then
echo -e "${BLUE}[dry-run]${NC} Would merge WP AI Gateway provider into $config_file"
echo -e "${BLUE}[dry-run]${NC} Provider: $AI_GATEWAY_PROVIDER_ID/$AI_GATEWAY_MODEL_ID via OPENAI_BASE_URL=$base_url and OPENAI_API_KEY=<redacted>"
echo -e "${BLUE}[dry-run]${NC} Provider: $AI_GATEWAY_PROVIDER_ID/$AI_GATEWAY_MODEL_ID (API model: $api_model_id) via OPENAI_BASE_URL=$base_url and OPENAI_API_KEY=<redacted>"
return 0
fi

Expand All @@ -163,14 +169,15 @@ ai_gateway_configure_opencode() {
return 0
fi

python3 - "$config_file" "$AI_GATEWAY_PROVIDER_ID" "$AI_GATEWAY_MODEL_ID" <<'PY'
python3 - "$config_file" "$AI_GATEWAY_PROVIDER_ID" "$AI_GATEWAY_MODEL_ID" "$api_model_id" <<'PY'
import json
import sys
from pathlib import Path

path = Path(sys.argv[1])
provider_id = sys.argv[2]
model_id = sys.argv[3]
api_model_id = sys.argv[4]

data = json.loads(path.read_text(encoding="utf-8"))
provider = data.setdefault("provider", {}).setdefault(provider_id, {})
Expand All @@ -183,7 +190,7 @@ provider["options"].setdefault("name", "wp-ai-gateway")
models = provider.setdefault("models", {})
model = models.setdefault(model_id, {})
model.setdefault("name", "WP AI Gateway site default")
model.setdefault("id", model_id)
model["id"] = api_model_id
model.setdefault("tool_call", True)
model.setdefault("temperature", True)
model.setdefault("limit", {"context": 128000, "output": 8192})
Expand Down
1 change: 1 addition & 0 deletions lib/summary.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ print_summary() {
echo " Base URL: $(ai_gateway_base_url)"
echo " Env file: $(ai_gateway_env_file)"
echo " Model: ${AI_GATEWAY_PROVIDER_ID}/${AI_GATEWAY_MODEL_ID}"
echo " API model: $(ai_gateway_api_model_id)"
echo " Route: ${AI_GATEWAY_ROUTE_PROVIDER} / ${AI_GATEWAY_ROUTE_MODEL}"
echo ""
fi
Expand Down
26 changes: 21 additions & 5 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,18 @@ while [[ $# -gt 0 ]]; do
AI_GATEWAY_ROUTE_MODEL="$2"
shift 2
;;
--ai-gateway-opencode-provider)
AI_GATEWAY_PROVIDER_ID="$2"
shift 2
;;
--ai-gateway-opencode-model)
AI_GATEWAY_MODEL_ID="$2"
shift 2
;;
--ai-gateway-api-model)
AI_GATEWAY_API_MODEL_ID="$2"
shift 2
;;
--rotate-ai-gateway-token)
ROTATE_AI_GATEWAY_TOKEN=true
shift
Expand Down Expand Up @@ -363,11 +371,17 @@ OPTIONS:
Backend WordPress AI Client provider for site-default
routing (default: openai)
--ai-gateway-model <id>
Backend provider model for site-default routing
(default: gpt-4o-mini)
Backend provider model for site-default routing
(default: gpt-4o-mini)
--ai-gateway-opencode-provider <id>
Provider identity shown by OpenCode
(default: wp-ai-gateway)
--ai-gateway-opencode-model <id>
OpenCode model ID exposed by the gateway provider
(default: site-default)
Model identity shown by OpenCode
(default: site-default)
--ai-gateway-api-model <id>
Model ID sent to WP AI Gateway (default: the OpenCode
model identity)
--rotate-ai-gateway-token
Mint a new gateway token instead of reusing the existing
.opencode/wp-ai-gateway.env value
Expand Down Expand Up @@ -401,7 +415,9 @@ ENVIRONMENT VARIABLES:
OPENCODE_SMALL_MODEL Override small model (e.g., anthropic/claude-haiku-4-5)
AI_GATEWAY_ROUTE_PROVIDER Backend provider used by --with-ai-gateway
AI_GATEWAY_ROUTE_MODEL Backend model used by --with-ai-gateway
AI_GATEWAY_MODEL_ID OpenCode gateway model id (default: site-default)
AI_GATEWAY_PROVIDER_ID Provider identity shown by OpenCode
AI_GATEWAY_MODEL_ID Model identity shown by OpenCode
AI_GATEWAY_API_MODEL_ID Model ID sent to WP AI Gateway
AI_GATEWAY_SITE_URL Public site URL for OPENAI_BASE_URL override
WITH_CLAUDE_CODE_AUTH false to skip direct OpenCode Claude Pro/Max auth
KIMAKI_BOT_TOKEN Discord bot token (skip interactive setup)
Expand Down
33 changes: 33 additions & 0 deletions tests/ai-gateway.sh
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,43 @@ assert provider["npm"] == "@ai-sdk/openai-compatible"
assert provider["env"] == ["OPENAI_API_KEY"]
assert provider["options"]["baseURL"] == "{env:OPENAI_BASE_URL}"
assert "site-default" in provider["models"]
assert provider["models"]["site-default"]["id"] == "site-default"
assert data["model"] == "anthropic/claude-sonnet-4-5"
assert "custom" in data["provider"]
PY

echo "==> visible gateway identity is separate from the API model"
AI_GATEWAY_PROVIDER_ID="openai"
AI_GATEWAY_MODEL_ID="gpt-5.6-sol"
AI_GATEWAY_API_MODEL_ID="site-default"
cat > "$SITE_PATH/opencode.json" <<'JSON'
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openai": {
"models": {
"gpt-5.6-sol": {
"id": "stale-model"
}
}
}
}
}
JSON

ai_gateway_configure_opencode
python3 - "$SITE_PATH/opencode.json" <<'PY'
import json
import sys

with open(sys.argv[1], encoding="utf-8") as handle:
data = json.load(handle)

model = data["provider"]["openai"]["models"]["gpt-5.6-sol"]
assert data["model"] == "openai/gpt-5.6-sol"
assert model["id"] == "site-default"
PY

echo
if [ "$FAIL" -gt 0 ]; then
echo "FAILED: $FAIL of $((PASS+FAIL)) assertion(s)"
Expand Down
8 changes: 7 additions & 1 deletion upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ while [[ $# -gt 0 ]]; do
--no-claude-code-auth) WITH_CLAUDE_CODE_AUTH=false; shift ;;
--ai-gateway-provider) AI_GATEWAY_ROUTE_PROVIDER="$2"; shift 2 ;;
--ai-gateway-model) AI_GATEWAY_ROUTE_MODEL="$2"; shift 2 ;;
--ai-gateway-opencode-provider) AI_GATEWAY_PROVIDER_ID="$2"; shift 2 ;;
--ai-gateway-opencode-model) AI_GATEWAY_MODEL_ID="$2"; shift 2 ;;
--ai-gateway-api-model) AI_GATEWAY_API_MODEL_ID="$2"; shift 2 ;;
--rotate-ai-gateway-token) ROTATE_AI_GATEWAY_TOKEN=true; shift ;;
--source-mode|--posture) SOURCE_MODE="$2"; SOURCE_MODE_EXPLICIT=true; shift 2 ;;
--not-owned) owned_discovery_add_exclusion "$2"; shift 2 ;;
Expand Down Expand Up @@ -238,7 +240,10 @@ USAGE:
./upgrade.sh --with-ai-gateway --rotate-ai-gateway-token
Explicitly mint a replacement gateway token.
./upgrade.sh --with-ai-gateway --ai-gateway-provider openai --ai-gateway-model gpt-4o-mini
Configure the WordPress gateway backend route.
Configure the WordPress gateway backend route.
./upgrade.sh --with-ai-gateway --ai-gateway-opencode-provider openai --ai-gateway-opencode-model gpt-5.6-sol --ai-gateway-api-model site-default
Show the resolved provider/model identity in
OpenCode while routing through site-default.
./upgrade.sh --no-claude-code-auth
Skip direct OpenCode Claude Pro/Max auth.
The managed auth plugin is installed by default
Expand Down Expand Up @@ -1322,6 +1327,7 @@ print_summary() {
log " Base URL: $(ai_gateway_base_url)"
log " Env file: $(ai_gateway_env_file)"
log " Model: ${AI_GATEWAY_PROVIDER_ID}/${AI_GATEWAY_MODEL_ID}"
log " API model: $(ai_gateway_api_model_id)"
log " Route: ${AI_GATEWAY_ROUTE_PROVIDER} / ${AI_GATEWAY_ROUTE_MODEL}"
fi

Expand Down
Loading