feat: implement internal credits handling in AI image generation

- Added support for internal credits feature in the generateImage action.
- Conditional reservation of credits based on the INTERNAL_CREDITS_ENABLED environment variable.
- Updated error handling to ensure credits are released or committed only when reservations are made.
This commit is contained in:
Matthias
2026-03-26 20:23:46 +01:00
parent 8daa4a91fb
commit 886a530f26

View File

@@ -17,6 +17,9 @@ export const generateImage = action({
aspectRatio: v.optional(v.string()), aspectRatio: v.optional(v.string()),
}, },
handler: async (ctx, args) => { handler: async (ctx, args) => {
const internalCreditsEnabled =
process.env.INTERNAL_CREDITS_ENABLED === "true";
const apiKey = process.env.OPENROUTER_API_KEY; const apiKey = process.env.OPENROUTER_API_KEY;
if (!apiKey) { if (!apiKey) {
throw new Error("OPENROUTER_API_KEY is not set"); throw new Error("OPENROUTER_API_KEY is not set");
@@ -32,13 +35,15 @@ export const generateImage = action({
throw new Error("User not found"); throw new Error("User not found");
} }
const reservationId = await ctx.runMutation(api.credits.reserve, { const reservationId = internalCreditsEnabled
? await ctx.runMutation(api.credits.reserve, {
estimatedCost: modelConfig.estimatedCostPerImage, estimatedCost: modelConfig.estimatedCostPerImage,
description: `Bildgenerierung — ${modelConfig.name}`, description: `Bildgenerierung — ${modelConfig.name}`,
model: modelId, model: modelId,
nodeId: args.nodeId, nodeId: args.nodeId,
canvasId: args.canvasId, canvasId: args.canvasId,
}); })
: null;
await ctx.runMutation(api.nodes.updateStatus, { await ctx.runMutation(api.nodes.updateStatus, {
nodeId: args.nodeId, nodeId: args.nodeId,
@@ -96,14 +101,18 @@ export const generateImage = action({
status: "done", status: "done",
}); });
if (reservationId) {
await ctx.runMutation(api.credits.commit, { await ctx.runMutation(api.credits.commit, {
transactionId: reservationId, transactionId: reservationId,
actualCost: creditCost, actualCost: creditCost,
}); });
}
} catch (error) { } catch (error) {
if (reservationId) {
await ctx.runMutation(api.credits.release, { await ctx.runMutation(api.credits.release, {
transactionId: reservationId, transactionId: reservationId,
}); });
}
await ctx.runMutation(api.nodes.updateStatus, { await ctx.runMutation(api.nodes.updateStatus, {
nodeId: args.nodeId, nodeId: args.nodeId,