fix(gemini): budget-check före bildhämtning så spärr triggars tidigt
This commit is contained in:
@@ -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.
|
// Trial startas först när e-posten är verifierad. En trial per verifierad e-post.
|
||||||
const [existingTrial] = await app.db
|
const [existingTrial] = await app.db
|
||||||
.select({ id: schema.trials.id })
|
.select({ userId: schema.trials.userId })
|
||||||
.from(schema.trials)
|
.from(schema.trials)
|
||||||
.where(eq(schema.trials.userId, stored.userId))
|
.where(eq(schema.trials.userId, stored.userId))
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|||||||
@@ -326,12 +326,21 @@ export class GeminiAamosClient implements AamosClient {
|
|||||||
const locale = options.localeContext ?? this.defaultLocale();
|
const locale = options.localeContext ?? this.defaultLocale();
|
||||||
const started = Date.now();
|
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(
|
const imageParts = await Promise.all(
|
||||||
input.imageUrls.slice(0, 6).map((url) => this.fetchOneImage(url, this.cfg.timeoutMs)),
|
input.imageUrls.slice(0, 6).map((url) => this.fetchOneImage(url, this.cfg.timeoutMs)),
|
||||||
);
|
);
|
||||||
|
|
||||||
const estimatedCostUsd = imageParts.length * COST_ESTIMATE_PER_IMAGE_USD;
|
if (imageParts.length === 0) {
|
||||||
if (await this.isOverBudget(estimatedCostUsd)) {
|
|
||||||
return {
|
return {
|
||||||
status: "failed",
|
status: "failed",
|
||||||
output: null,
|
output: null,
|
||||||
@@ -416,8 +425,8 @@ export class GeminiAamosClient implements AamosClient {
|
|||||||
const locale = options.localeContext ?? this.defaultLocale();
|
const locale = options.localeContext ?? this.defaultLocale();
|
||||||
const started = Date.now();
|
const started = Date.now();
|
||||||
|
|
||||||
const imageParts = await this.fetchImageParts(imageUrls, this.cfg.timeoutMs);
|
const imageCount = Math.min(imageUrls.length, 6);
|
||||||
const estimatedCostUsd = imageParts.length * costEstimatePerImage;
|
const estimatedCostUsd = imageCount * costEstimatePerImage;
|
||||||
if (await this.isOverBudget(estimatedCostUsd)) {
|
if (await this.isOverBudget(estimatedCostUsd)) {
|
||||||
return {
|
return {
|
||||||
status: "failed",
|
status: "failed",
|
||||||
@@ -426,6 +435,15 @@ export class GeminiAamosClient implements AamosClient {
|
|||||||
} as AamosResult<T>;
|
} as AamosResult<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<T>;
|
||||||
|
}
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
contents: [{ parts: [{ text: prompt }, ...imageParts] }],
|
contents: [{ parts: [{ text: prompt }, ...imageParts] }],
|
||||||
generationConfig: {
|
generationConfig: {
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import type {
|
|||||||
OpsFeedbackBlock,
|
OpsFeedbackBlock,
|
||||||
OpsWallBlock,
|
OpsWallBlock,
|
||||||
OpsWallTile,
|
OpsWallTile,
|
||||||
|
OpsAlarm,
|
||||||
|
OpsAlarmBlock,
|
||||||
} from "@app/shared-types";
|
} from "@app/shared-types";
|
||||||
import { SUBSCRIPTION_PLANS, type SubscriptionPlan } from "@app/shared-types";
|
import { SUBSCRIPTION_PLANS, type SubscriptionPlan } from "@app/shared-types";
|
||||||
import type { Database } from "./client.js";
|
import type { Database } from "./client.js";
|
||||||
|
|||||||
@@ -139,13 +139,14 @@ describe("buildWall", () => {
|
|||||||
expect(brott.tone).toBe("warn");
|
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;
|
const tiles = buildWall(baseSummary()).boards[0]!.tiles;
|
||||||
expect(tiles.map((t) => t.label)).toEqual([
|
expect(tiles.map((t) => t.label)).toEqual([
|
||||||
"MRR",
|
"MRR",
|
||||||
"Aktiva nu",
|
"Aktiva nu",
|
||||||
"Betalande",
|
"Betalande",
|
||||||
"Trial-konv",
|
"Trial-konv",
|
||||||
|
"AI-budget",
|
||||||
"Workers",
|
"Workers",
|
||||||
"Allergen-brott",
|
"Allergen-brott",
|
||||||
]);
|
]);
|
||||||
|
|||||||
Reference in New Issue
Block a user