Skip to content

feat(ai): run the AI analyst through any Gemini-compatible gateway - #334

Open
tsstod wants to merge 1 commit into
simplifaisoul:masterfrom
tsstod:feat/ai-gateway
Open

feat(ai): run the AI analyst through any Gemini-compatible gateway#334
tsstod wants to merge 1 commit into
simplifaisoul:masterfrom
tsstod:feat/ai-gateway

Conversation

@tsstod

@tsstod tsstod commented Sep 11, 2026

Copy link
Copy Markdown

Lets the AI analyst (/api/ai/analyze, /api/ai/briefing, /api/ai/overview) run against any server that speaks the Gemini REST API, not just Google. With neither new variable set, nothing changes.

Why

The analyst could only talk to generativelanguage.googleapis.com, and only with a GEMINI_API_KEY_* set. Without one, analyze and briefing return 503 NO_API_KEY and the one-click overview drops to the heuristic analyst. .env.example didn't mention the Gemini keys at all, so a fresh self-hosted install never gets a model.

Gateways such as OmniRoute serve Gemini's own endpoint (/v1beta/models/{model}:generateContent) and route each request to whatever provider they're configured with, free-tier ones included. The Gemini SDK already accepts a baseUrl, so a gateway needs no second client.

What changed

  • OSIRIS_AI_BASE_URL points the existing SDK at the gateway. OSIRIS_AI_MODEL overrides the model id (default stays gemini-2.0-flash; auto lets OmniRoute choose). Both are read per request, not at import.
  • No Gemini key needed behind a gateway. The SDK refuses to run without a key, so a stand-in is passed. OSIRIS_AI_API_KEY is used if the gateway wants a real one. Real GEMINI_API_KEY_* values still win when both are set.
  • Reasoning no longer leaks into the output. Reasoning models behind a gateway return their chain of thought as parts flagged thought: true. SDK 0.24's response.text() concatenates every part, so a briefing opened with the model talking to itself. The new responseText() drops those parts. It still calls text() first, so a blocked response keeps surfacing as SAFETY_BLOCKED.
  • One shared key lookup. The three routes each carried their own copy of the GEMINI_API_KEY_1..8 loop; they now share getServerApiKeys().
  • Truthful overview label. The overview footer said "GEMINI 2.0 FLASH" whatever answered. The route now returns the model id and the label shows that.
  • .env.example gains an AI ANALYST section covering the Gemini keys and the gateway variables, including the Docker note: use host.docker.internal, not 127.0.0.1.

Testing

Notes

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

@tsstod is attempting to deploy a commit to the Developing Osiris' projects Team on Vercel.

A member of the Team first needs to authorize it.

The analyst could only talk to Google, and only with a GEMINI_API_KEY_*
set. Without one, /api/ai/analyze and /api/ai/briefing returned 503 and
the one-click overview fell back to the heuristic.

OSIRIS_AI_BASE_URL now points the existing Gemini SDK at any server that
speaks the Gemini REST API, and OSIRIS_AI_MODEL overrides the model id.
A local OmniRoute, for example, serves
/v1beta/models/{model}:generateContent and routes each request to a
provider it picks ('auto'). No Gemini key is needed then. The SDK still
insists on one, so a stand-in is passed (OSIRIS_AI_API_KEY if the
gateway wants a real one). With neither variable set, behaviour is
unchanged.

Reasoning models behind a gateway return their chain of thought as
parts flagged `thought: true`. SDK 0.24's text() concatenates every
part, so briefings opened with the model talking to itself. The
responseText() helper drops those parts. It still calls text() first,
so a blocked response keeps surfacing as SAFETY_BLOCKED.

The three routes each carried their own copy of the key loop; they now
share getServerApiKeys(). The overview label read "GEMINI 2.0 FLASH"
whatever answered, so the route now returns the model id and the label
shows that.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tsstod

tsstod commented Sep 11, 2026

Copy link
Copy Markdown
Author

The red Vercel – osiris check here is Vercel waiting for a team member to authorize a deploy from a fork. No build has run, so here's a local one instead:

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant