refactor: strip Gemini from the platform, and level up the architecture_mapper
Two things.
1. The architecture_mapper proposal, applied AND made durable.
The GLM proposal (019fddd9) was accepted in full: the agent's system_prompt now
carries the Mermaid-first constraint and its brain was rewritten. Both verified
against the live row and the .h5 file.
But `apply_identity` writes `UPDATE agents SET system_prompt` and
`apply_brain_consolidation` writes that agent's brain — neither touches the team
TEMPLATE. That agent is mission-scoped, so the improvement would have died with
the mission. The model's actual insight was sharp and worth keeping: "Mermaid
diagrams beat prose" lived in the brain SEED and not in the system PROMPT, so it
only applied when the agent happened to consult its brain. That constraint is
now in templates/teams/codebase_research.toml, where every future Codebase
Research team inherits it.
(The proposal's second item mostly restated anti-patterns the seed already
lists, so the seed is unchanged. Applying an LLM's suggestion is not the same as
agreeing with all of it.)
2. Gemini is gone.
Removed: the `gemini.default` provider alias and its `is_exact_provider_match`
prefix, GEMINI_API_KEY forwarding to agent containers, the evaluator's
gemini->gemini family row, the model selectors in claws/teams/planner and in
TeamWizard + AgentComputer, and the commented provider block in the runtime
config example (whose ZEROCLAW_AGENT_MAP example still mapped a worker_gemini
that no longer existed).
`provider_alias_for("gemini")` now returns claude_cli.default via the
unrecognised-model branch, which LOGS. A stray gemini binding degrades visibly
rather than resolving to a provider row we no longer ship. A test pins that, and
another pins that GEMINI_API_KEY is forwarded in NEITHER auth mode, so adding it
back to the list is a visible change rather than an accident.
Avatar generation is DELETED, not disabled — it called Gemini's image model, and
there is no alternative: Claude and Kimi are text-only, and z.ai answers
"Unknown Model" for cogview-3-flash and cogview-4 on our plan (measured, not
assumed). AvatarModal keeps UPLOAD, which never needed a provider; only the
prompt-generation half is gone.
240 backend lib tests, 89 frontend tests, clean tsc + eslint, build succeeds.
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
// Local Next route (NOT proxied — a specific path beats the /api/[...path]
|
||||
// catch-all): generates an agent avatar with Gemini's image model ("Nano
|
||||
// Banana", gemini-2.5-flash-image) using GEMINI_API_KEY from the frontend env,
|
||||
// and returns a base64 data URL. Saving the chosen image is a separate
|
||||
// PATCH /api/claws/{id} {avatar} (the existing backend route).
|
||||
|
||||
import { NextResponse, type NextRequest } from "next/server";
|
||||
|
||||
import { resolveBearer } from "@/lib/auth/bearer";
|
||||
|
||||
const MODEL = "gemini-2.5-flash-image";
|
||||
const ENDPOINT = `https://generativelanguage.googleapis.com/v1beta/models/${MODEL}:generateContent`;
|
||||
|
||||
interface InlineData { data?: string; mimeType?: string; mime_type?: string }
|
||||
interface GeminiPart { inlineData?: InlineData; inline_data?: InlineData }
|
||||
interface GeminiResponse { candidates?: Array<{ content?: { parts?: GeminiPart[] } }> }
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const token = await resolveBearer();
|
||||
if (!token) return NextResponse.json({ error: "unauthenticated" }, { status: 401 });
|
||||
|
||||
const key = process.env.GEMINI_API_KEY;
|
||||
if (!key) return NextResponse.json({ error: "image generation is not configured (set GEMINI_API_KEY)" }, { status: 503 });
|
||||
|
||||
let prompt = "";
|
||||
try {
|
||||
const body = (await request.json()) as { prompt?: unknown };
|
||||
prompt = String(body?.prompt ?? "").trim();
|
||||
} catch {
|
||||
/* fall through to the 400 below */
|
||||
}
|
||||
if (!prompt) return NextResponse.json({ error: "prompt required" }, { status: 400 });
|
||||
|
||||
let upstream: Response;
|
||||
try {
|
||||
upstream = await fetch(ENDPOINT, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json", "x-goog-api-key": key },
|
||||
body: JSON.stringify({
|
||||
contents: [{ parts: [{ text: `A clean, centered square avatar portrait for an AI agent. ${prompt}` }] }],
|
||||
generationConfig: { responseModalities: ["IMAGE"] },
|
||||
}),
|
||||
});
|
||||
} catch {
|
||||
return NextResponse.json({ error: "could not reach the image service" }, { status: 502 });
|
||||
}
|
||||
|
||||
if (!upstream.ok) {
|
||||
const detail = await upstream.text().catch(() => "");
|
||||
return NextResponse.json({ error: `image service error (${upstream.status})`, detail: detail.slice(0, 400) }, { status: 502 });
|
||||
}
|
||||
|
||||
const data = (await upstream.json().catch(() => null)) as GeminiResponse | null;
|
||||
const parts = data?.candidates?.[0]?.content?.parts ?? [];
|
||||
const part = parts.find((p) => p.inlineData?.data || p.inline_data?.data);
|
||||
const inline = part?.inlineData ?? part?.inline_data;
|
||||
if (!inline?.data) {
|
||||
return NextResponse.json({ error: "the model did not return an image — try a different prompt" }, { status: 502 });
|
||||
}
|
||||
const mime = inline.mimeType ?? inline.mime_type ?? "image/png";
|
||||
return NextResponse.json({ image: `data:${mime};base64,${inline.data}` });
|
||||
}
|
||||
Reference in New Issue
Block a user