Skip to content

Gemini-only β€” remove OpenAI (audit + handoff) ​

Historical 2026-06-08 handoff. Hermes and every Edge Function referenced below are now canonically owned in this repository under services/hermes-server/ and supabase/functions/.

Date: 2026-06-08 Goal: No OpenAI anywhere. The AI system is Hermes (agent/gateway) with Gemini internally.

The Flutter client has no OpenAI provider; OpenAI-compatible naming describes only the wire format. Provider implementation is owned here by Hermes and the shared Edge Function client.


Audit (read-only, 2026-06-08) β€” OpenAI is dormant ​

Against Supabase project jrsgosnnyjonxaesqtln:

  • hermes_config is 100% Gemini β€” no gpt-* pin:
    keyvalue
    model.chatgoogle/gemini-3-flash-preview
    model.chat.targetgoogle/gemini-3.5-flash
    model.reasoninggoogle/gemini-3-pro-preview
    model.reasoning.targetgoogle/gemini-3.1-pro
  • Every AI edge function passes Gemini model IDs in its own logic (gemini-2.5-flash, gemini-2.5-pro, also sonar-pro). Nothing passes a gpt-* model, so the OpenAI branch is never executed.
  • The OpenAI code is not function-specific. It lives in the shared _shared/aiClient.ts (bundled into ~28 AI functions): a gpt- branch in getProviderConfig, the OPENAI_API constant, the OPENAI_API_KEY env read, and gpt-4o* rows in the cost table.
  • generate-property-image and the ~88 non-AI functions: no OpenAI markers.

Conclusion: OpenAI is present but inert β€” dead code in one shared helper + an unused secret. Removing it is low-risk (zero functional impact, since nothing uses gpt-*).


Action 1 (kill-switch) β€” βœ… ALREADY SATISFIED ​

Verified 2026-06-08 via supabase secrets list --project-ref jrsgosnnyjonxaesqtln: there is no OPENAI_API_KEY secret β€” it was never set (GOOGLE_AI_API_KEY for Gemini is present). So the edge functions' OpenAI path is already non-functional: if a gpt-* model were ever passed, getProviderConfig throws OPENAI_API_KEY is not configured and never reaches api.openai.com.

Nothing to remove. If a future change ever adds the secret, drop it with:

bash
supabase secrets unset OPENAI_API_KEY --project-ref jrsgosnnyjonxaesqtln

Net: OpenAI in the edge functions is doubly dormant β€” no caller passes gpt-* (Action 2 removes that dead code), and the key is absent (this action).


Action 2 (permanent removal at the source) β€” patch _shared/aiClient.ts ​

Edit supabase/functions/_shared/aiClient.ts here and deploy the affected allowlisted functions from the canonical Flutter pipeline. One edit propagates to all bundled AI functions.

a) Delete the OPENAI_API constant:

ts
// remove this line:
const OPENAI_API = 'https://api.openai.com/v1/chat/completions';

b) Remove the gpt- branch in getProviderConfig (Gemini-only):

ts
// BEFORE
function getProviderConfig(model: string): { url: string; apiKey: string; resolvedModel: string } {
  if (model.startsWith('gpt-')) {
    const key = Deno.env.get('OPENAI_API_KEY');
    if (!key) throw new Error('OPENAI_API_KEY is not configured');
    return { url: OPENAI_API, apiKey: key, resolvedModel: model };
  }
  // Google models β€” use native Gemini API with OpenAI-compatible endpoint
  const key = Deno.env.get('GOOGLE_AI_API_KEY');
  if (!key) throw new Error('GOOGLE_AI_API_KEY is not configured β€” set it in Supabase Edge Function secrets');
  return { url: GOOGLE_AI_API, apiKey: key, resolvedModel: resolveGoogleModel(model) };
}

// AFTER (Gemini-only)
function getProviderConfig(model: string): { url: string; apiKey: string; resolvedModel: string } {
  // Gemini-only. The OpenAI provider branch has been removed; any stray
  // non-Gemini id is coerced to Gemini by resolveGoogleModel, so no request
  // can reach api.openai.com.
  const key = Deno.env.get('GOOGLE_AI_API_KEY');
  if (!key) throw new Error('GOOGLE_AI_API_KEY is not configured β€” set it in Supabase Edge Function secrets');
  return { url: GOOGLE_AI_API, apiKey: key, resolvedModel: resolveGoogleModel(model) };
}

c) Harden resolveGoogleModel so a stray non-Gemini id can't reach the Google endpoint:

ts
// BEFORE
function resolveGoogleModel(model: string): string {
  return GOOGLE_MODEL_MAP[model] ?? model;
}
// AFTER
function resolveGoogleModel(model: string): string {
  const mapped = GOOGLE_MODEL_MAP[model] ?? model;
  return mapped.startsWith('gemini') ? mapped : 'gemini-2.5-flash';
}

d) Delete the gpt-* cost rows in MODEL_COSTS_PER_1M:

ts
// remove:
'gpt-4o-mini': { input: 0.15, output: 0.60 },
'gpt-4o': { input: 5.00, output: 15.00 },

Then redeploy the AI functions (normal pipeline). Note: doing this per-function via the Supabase MCP was rejected β€” it would patch only one of ~28 bundles and diverge from this source, reintroducing OpenAI on the next source deploy. Fix it here, once.

Verify after deploy: recent ai-assistant rows in ai_usage_logs.model show only gemini-*; grep the deployed bundles for api.openai.com β†’ none.


Action 3 (primary system) β€” confirm Hermes is Gemini-only ​

/ai chat routes through Hermes (hermes.aldilaijan.com) first; the edge functions are only the fallback. Hermes is a separate repo this agent can't see. This is the one genuinely-important remaining item. Run these in the Hermes repo:

1. Grep for a real OpenAI provider path (an "OpenAI-compatible SSE" format comment is fine; api.openai.com, gpt-* model selection, or OPENAI_API_KEY are not):

bash
grep -rniE 'api\.openai\.com|OPENAI_API_KEY|[^a-z]gpt-[0-9a-z]' \
  --include='*.ts' --include='*.js' --include='*.py' .

Expected: no hits.

2. Does Hermes share _shared/aiClient.ts / the same getProviderConfig?

bash
grep -rn 'getProviderConfig\|aiClient' --include='*.ts' .
  • If yes β†’ the single Action 2 patch above also fixes Hermes (one edit covers both surfaces).
  • If Hermes has its own provider code β†’ apply the same removal there (no model.startsWith('gpt-') branch; default/fallback model is a Gemini id).

3. Confirm model resolution is Gemini-only. hermes_config is already 100% Gemini (verified); check the code's hardcoded fallback is too (per HERMES_MODEL_CONFIG.md: google/gemini-3-flash-preview / …-pro-preview):

bash
grep -rniE 'FALLBACK|default.*model|model.*default' --include='*.ts' .

4. Check Hermes' runtime env (host/platform secret store, .env*) for OPENAI_API_KEY β†’ remove if present.

5. Runtime proof β€” send one chat through Hermes, then:

sql
select model, count(*) from public.ai_usage_logs
where created_at > now() - interval '15 min' group by model;  -- expect only gemini-*

Only once Hermes is confirmed is "no OpenAI in my system" fully true.


This repo (Flutter) β€” done ​

There was never an OpenAI provider here β€” only the OpenAI-compatible SSE wire format. The misleadingly-named helper has been renamed (streamOpenAIEdgeFunction β†’ streamSseChatEdgeFunction, file openai_edge_stream.dart β†’ sse_chat_edge_stream.dart) so nothing in the Flutter codebase implies the OpenAI provider. The app remains provider-agnostic β€” it just streams whatever Hermes/Gemini returns.

Aldilaijan & Khobara Real Estate Platform