From 7dda0fad00a6bc0cf965014c7d0f67bbe6fba089 Mon Sep 17 00:00:00 2001 From: "Sven (AAMOS AI)" Date: Wed, 12 Aug 2026 16:30:49 +0700 Subject: [PATCH] =?UTF-8?q?fix(gemini):=20budget-check=20f=C3=B6re=20bildh?= =?UTF-8?q?=C3=A4mtning=20s=C3=A5=20sp=C3=A4rr=20triggars=20tidigt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/routes/auth.ts | 2 +- packages/ai-contracts/src/gemini.ts | 26 +++++++++++++++++++++---- packages/database/src/ops-summary.ts | 2 ++ packages/database/test/ops-wall.test.ts | 3 ++- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/apps/api/src/routes/auth.ts b/apps/api/src/routes/auth.ts index 35c43d9..38ea7b4 100644 --- a/apps/api/src/routes/auth.ts +++ b/apps/api/src/routes/auth.ts @@ -232,7 +232,7 @@ export async function authRoutes(app: FastifyInstance) { // Trial startas först när e-posten är verifierad. En trial per verifierad e-post. const [existingTrial] = await app.db - .select({ id: schema.trials.id }) + .select({ userId: schema.trials.userId }) .from(schema.trials) .where(eq(schema.trials.userId, stored.userId)) .limit(1); diff --git a/packages/ai-contracts/src/gemini.ts b/packages/ai-contracts/src/gemini.ts index 3c4d137..a62ca2d 100644 --- a/packages/ai-contracts/src/gemini.ts +++ b/packages/ai-contracts/src/gemini.ts @@ -326,12 +326,21 @@ export class GeminiAamosClient implements AamosClient { const locale = options.localeContext ?? this.defaultLocale(); const started = Date.now(); + const imageCount = Math.min(input.imageUrls.length, 6); + const estimatedCostUsd = imageCount * COST_ESTIMATE_PER_IMAGE_USD; + if (await this.isOverBudget(estimatedCostUsd)) { + return { + status: "failed", + output: null, + error: "Global Gemini-dagsbudget är förbrukad.", + }; + } + const imageParts = await Promise.all( input.imageUrls.slice(0, 6).map((url) => this.fetchOneImage(url, this.cfg.timeoutMs)), ); - const estimatedCostUsd = imageParts.length * COST_ESTIMATE_PER_IMAGE_USD; - if (await this.isOverBudget(estimatedCostUsd)) { + if (imageParts.length === 0) { return { status: "failed", output: null, @@ -416,8 +425,8 @@ export class GeminiAamosClient implements AamosClient { const locale = options.localeContext ?? this.defaultLocale(); const started = Date.now(); - const imageParts = await this.fetchImageParts(imageUrls, this.cfg.timeoutMs); - const estimatedCostUsd = imageParts.length * costEstimatePerImage; + const imageCount = Math.min(imageUrls.length, 6); + const estimatedCostUsd = imageCount * costEstimatePerImage; if (await this.isOverBudget(estimatedCostUsd)) { return { status: "failed", @@ -426,6 +435,15 @@ export class GeminiAamosClient implements AamosClient { } as AamosResult; } + const imageParts = await this.fetchImageParts(imageUrls, this.cfg.timeoutMs); + if (imageParts.length === 0) { + return { + status: "failed", + output: null, + error: "Global Gemini-dagsbudget är förbrukad.", + } as AamosResult; + } + const payload = { contents: [{ parts: [{ text: prompt }, ...imageParts] }], generationConfig: { diff --git a/packages/database/src/ops-summary.ts b/packages/database/src/ops-summary.ts index 816887b..7c16ea9 100644 --- a/packages/database/src/ops-summary.ts +++ b/packages/database/src/ops-summary.ts @@ -15,6 +15,8 @@ import type { OpsFeedbackBlock, OpsWallBlock, OpsWallTile, + OpsAlarm, + OpsAlarmBlock, } from "@app/shared-types"; import { SUBSCRIPTION_PLANS, type SubscriptionPlan } from "@app/shared-types"; import type { Database } from "./client.js"; diff --git a/packages/database/test/ops-wall.test.ts b/packages/database/test/ops-wall.test.ts index 847beec..dafda56 100644 --- a/packages/database/test/ops-wall.test.ts +++ b/packages/database/test/ops-wall.test.ts @@ -139,13 +139,14 @@ describe("buildWall", () => { expect(brott.tone).toBe("warn"); }); - it("alla sex tiles finns i rätt ordning", () => { + it("alla sju tiles finns i rätt ordning", () => { const tiles = buildWall(baseSummary()).boards[0]!.tiles; expect(tiles.map((t) => t.label)).toEqual([ "MRR", "Aktiva nu", "Betalande", "Trial-konv", + "AI-budget", "Workers", "Allergen-brott", ]);