feat: add local auth billing and usage management

This commit is contained in:
inman committed 2026-08-12 12:13:06 +08:00
1 parent f642b5e71f
commit 196fdde83f
119 files changed
+15695 -2650

No files matched your search

+4 -3
View File
@@ -2,6 +2,7 @@ import { clearGenerationJobLock, getGenerationJob, updateGenerationJob } from "@
import { jsonError, jsonOk } from "@/lib/server/api";
import { authenticatePublicApiRequest, publicApiOwnerId } from "@/lib/server/public-api-auth";
import { publicApiError } from "@/lib/server/public-api-response";
import { refundGenerationCharge } from "@/lib/server/billing-service";
export const runtime = "nodejs";
@@ -16,12 +17,12 @@ export async function POST(request: Request, context: { params: Promise<{ id: st
if (["succeeded", "failed", "expired", "cancelled"].includes(job.status)) {
return jsonOk({ job });
}
await updateGenerationJob(id, {
const cancelled = await updateGenerationJob(id, {
status: "cancelled",
completedAt: new Date().toISOString()
});
const cancelled = await clearGenerationJobLock(id);
return jsonOk({ job: cancelled });
const refunded = await refundGenerationCharge(cancelled, "任务已取消") || cancelled;
return jsonOk({ job: await clearGenerationJobLock(refunded.id) });
} catch (error) {
return publicApiError(error);
}
+1 -1
View File
@@ -52,7 +52,7 @@ function parseStatus(value: string | null): GenerationStatus | undefined {
function parseCapability(value: string | null): GenerationCapability | undefined {
if (!value) return undefined;
if (["image.generate", "image.inpaint", "image.upscale", "video.generate"].includes(value)) {
if (["image.generate", "video.generate"].includes(value)) {
return value as GenerationCapability;
}
throw new Error(`Unsupported capability filter: ${value}`);
+4 -6
View File
@@ -38,7 +38,7 @@ export async function GET(request: Request) {
name: { type: "string", example: "result.png" },
url: { type: "string", format: "uri" },
storagePath: { type: "string" },
source: { type: "string", enum: ["upload", "generated", "edited", "upscaled", "external", "seed"] },
source: { type: "string", enum: ["upload", "generated", "external", "seed"] },
tags: { type: "array", items: { type: "string" } },
metadata: { type: "object", additionalProperties: true },
createdAt: { type: "string", format: "date-time" },
@@ -83,7 +83,7 @@ export async function GET(request: Request) {
},
GenerationCapability: {
type: "string",
enum: ["image.generate", "image.inpaint", "image.upscale", "video.generate"]
enum: ["image.generate", "video.generate"]
},
GenerationStatus: {
type: "string",
@@ -121,11 +121,9 @@ export async function GET(request: Request) {
},
width: { type: "integer", example: 1440 },
height: { type: "integer", example: 2560 },
scale: { type: "number", minimum: 1, maximum: 100, description: "Jimeng text influence for image.generate and detail strength for image.upscale." },
scale: { type: "number", minimum: 1, maximum: 100, description: "Jimeng text influence for image.generate." },
force_single: { type: "boolean" },
quality: { type: "string", enum: ["low", "medium", "high"], description: "EvoLink image quality for image.generate and image.inpaint." },
resolution: { type: "string", enum: ["4k", "8k"], description: "Upscale resolution for image.upscale." },
seed: { type: "integer" },
quality: { type: "string", enum: ["low", "medium", "high"], description: "EvoLink image quality for image.generate." },
priority: { type: "integer", minimum: -100, maximum: 100 },
webhookUrl: { type: "string", format: "uri" },
idempotencyKey: { type: "string", description: "Optional body-level idempotency key. Header Idempotency-Key is preferred." }