feat(gemini): Skiva 1 – Gemini 2.5 Flash som lärar-tier för kylskåpsskanning
- Gemini-adapter bakom AamosClient-interface (AAMOS_MODE=gemini) - Serversida/worker: hämtar bild, anropar Gemini, mappar mot canonical_ingredients - Kostnad/tokens bokförs i ai_usage_counters; global dagsbudget via BudgetStore - Redis-backed budget i worker, in-memory i tester - Migration 0019: ai_cost_usd_microcents - Hermetiska tester med inspelad fixture; separat pnpm eval:scan - docs/09 uppdaterad ärligt: AAMOS-status, Gemini-flöde, säkerhet/kostnad - REQUIRE_REAL=1 stödjer AAMOS_MODE=gemini; deploy-grind uppdaterad
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
type TaskOutput,
|
||||
} from "./tasks.js";
|
||||
import { mockOutputFor } from "./mock.js";
|
||||
import { GeminiAamosClient, type BudgetStore } from "./gemini.js";
|
||||
|
||||
import type { LocaleContext } from "@app/shared-types";
|
||||
|
||||
@@ -31,6 +32,8 @@ export interface AamosResult<T extends AamosTaskType> {
|
||||
promptVersion?: string | undefined;
|
||||
latencyMs?: number | undefined;
|
||||
costUsd?: number | undefined;
|
||||
inputTokens?: number | undefined;
|
||||
outputTokens?: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,12 +251,44 @@ export interface AamosEnv {
|
||||
AAMOS_API_URL?: string | undefined;
|
||||
AAMOS_API_KEY?: string | undefined;
|
||||
AAMOS_TIMEOUT_MS?: string | undefined;
|
||||
|
||||
GEMINI_API_KEY?: string | undefined;
|
||||
GEMINI_MODEL?: string | undefined;
|
||||
GEMINI_TIMEOUT_MS?: string | undefined;
|
||||
GEMINI_DAILY_BUDGET_USD?: string | undefined;
|
||||
}
|
||||
|
||||
/** Fabrik: http mot riktiga AAMOS (default), mock för dev/test. */
|
||||
export function createAamosClient(env: AamosEnv = process.env): AamosClient {
|
||||
export interface CreateAamosClientOptions {
|
||||
budgetStore?: BudgetStore;
|
||||
fetchImpl?: typeof fetch;
|
||||
}
|
||||
|
||||
/** Fabrik: http mot riktiga AAMOS, gemini-lärar-tier, eller mock för dev/test. */
|
||||
export function createAamosClient(
|
||||
env: AamosEnv = process.env,
|
||||
options: CreateAamosClientOptions = {},
|
||||
): AamosClient {
|
||||
const mode = env.AAMOS_MODE ?? "http";
|
||||
if (mode === "mock") return new MockAamosClient();
|
||||
|
||||
if (mode === "gemini") {
|
||||
const apiKey = env.GEMINI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error(
|
||||
"AAMOS_MODE=gemini kräver GEMINI_API_KEY. " +
|
||||
"Sätt AAMOS_MODE=mock för lokal utveckling utan Gemini-åtkomst.",
|
||||
);
|
||||
}
|
||||
return new GeminiAamosClient({
|
||||
apiKey,
|
||||
model: env.GEMINI_MODEL,
|
||||
timeoutMs: env.GEMINI_TIMEOUT_MS ? Number(env.GEMINI_TIMEOUT_MS) : undefined,
|
||||
dailyBudgetUsd: env.GEMINI_DAILY_BUDGET_USD ? Number(env.GEMINI_DAILY_BUDGET_USD) : undefined,
|
||||
budgetStore: options.budgetStore,
|
||||
fetchImpl: options.fetchImpl,
|
||||
});
|
||||
}
|
||||
|
||||
const baseUrl = env.AAMOS_API_URL;
|
||||
const apiKey = env.AAMOS_API_KEY;
|
||||
if (!baseUrl || !apiKey) {
|
||||
@@ -266,6 +301,7 @@ export function createAamosClient(env: AamosEnv = process.env): AamosClient {
|
||||
baseUrl,
|
||||
apiKey,
|
||||
timeoutMs: env.AAMOS_TIMEOUT_MS ? Number(env.AAMOS_TIMEOUT_MS) : undefined,
|
||||
fetchImpl: options.fetchImpl,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user