feat(console): add quota reset support action (#47313)

This commit is contained in:
黑墨水鱼 2026-09-05 02:47:06 +08:00 committed by GitHub
parent 5d5c35ee71
commit 5cf9f517cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 89 additions and 0 deletions

View file

@ -0,0 +1,24 @@
import type { APIEvent } from "@solidjs/start/server"
import { Quota } from "@opencode-ai/console-core/quota.js"
import { safeEqual } from "@opencode-ai/console-core/util/crypto.js"
import { Resource } from "@opencode-ai/console-resource"
import z from "zod"
const Body = z.object({
workspaceID: z.string().startsWith("wrk_"),
plan: z.enum(["lite", "subscription"]),
})
export async function POST(event: APIEvent) {
if (!safeEqual(event.request.headers.get("authorization") ?? "", `Bearer ${Resource.SUPPORT_API_KEY.value}`)) {
return Response.json({ error: "Unauthorized" }, { status: 401 })
}
const body = Body.safeParse(await event.request.json().catch(() => undefined))
if (!body.success) {
return Response.json({ error: "Invalid request", issues: body.error.issues }, { status: 400 })
}
return Quota.reset(body.data)
.then((result) => Response.json({ success: true, message: "Usage counters reset to zero", result }))
.catch((error) => Response.json({ error: error instanceof Error ? error.message : String(error) }, { status: 400 }))
}

View file

@ -0,0 +1,65 @@
import { z } from "zod"
import { and, Database, eq, isNull } from "./drizzle"
import { LiteTable, SubscriptionTable } from "./schema/billing.sql"
import { Identifier } from "./identifier"
import { fn } from "./util/fn"
export namespace Quota {
// Zero all usage counters of one plan for a workspace, using the same
// workspace-scoped addressing as unsubscribeLite/unsubscribeBlack and
// Billing.subtractLiteUsage. Timestamps are left untouched on purpose: a
// zeroed counter with a current-window stamp reads as empty and the next
// write accumulates on top of zero, so the active windows stay undisturbed.
export const reset = fn(
z.object({
workspaceID: Identifier.schema("workspace"),
plan: z.enum(["lite", "subscription"]),
}),
async (input) => {
if (input.plan === "lite") {
return Database.transaction(async (db) => {
const where = and(eq(LiteTable.workspaceID, input.workspaceID), isNull(LiteTable.timeDeleted))
const rows = await db
.select({
rollingUsage: LiteTable.rollingUsage,
weeklyUsage: LiteTable.weeklyUsage,
monthlyUsage: LiteTable.monthlyUsage,
})
.from(LiteTable)
.where(where)
if (rows.length === 0) throw new Error("No lite usage counters found for workspace")
await db.update(LiteTable).set({ rollingUsage: 0, weeklyUsage: 0, monthlyUsage: 0 }).where(where)
return {
plan: "lite" as const,
before: {
rollingUsage: rows.reduce((sum, row) => sum + (row.rollingUsage ?? 0), 0),
weeklyUsage: rows.reduce((sum, row) => sum + (row.weeklyUsage ?? 0), 0),
monthlyUsage: rows.reduce((sum, row) => sum + (row.monthlyUsage ?? 0), 0),
},
}
})
}
if (input.plan === "subscription") {
return Database.transaction(async (db) => {
const where = and(eq(SubscriptionTable.workspaceID, input.workspaceID), isNull(SubscriptionTable.timeDeleted))
const rows = await db
.select({ rollingUsage: SubscriptionTable.rollingUsage, fixedUsage: SubscriptionTable.fixedUsage })
.from(SubscriptionTable)
.where(where)
if (rows.length === 0) throw new Error("No subscription usage counters found for workspace")
await db.update(SubscriptionTable).set({ rollingUsage: 0, fixedUsage: 0 }).where(where)
return {
plan: "subscription" as const,
before: {
rollingUsage: rows.reduce((sum, row) => sum + (row.rollingUsage ?? 0), 0),
fixedUsage: rows.reduce((sum, row) => sum + (row.fixedUsage ?? 0), 0),
},
}
})
}
throw new Error(`Unknown plan: ${input.plan}`)
},
)
}