summaryrefslogtreecommitdiffhomepage
path: root/packages/console/core
diff options
context:
space:
mode:
authorFrank <[email protected]>2026-01-14 21:20:23 -0500
committerFrank <[email protected]>2026-01-14 21:20:26 -0500
commite03932e586e89cc30015e6a5006ed5e83881a05c (patch)
tree5655f0c063b717399a71a07625a8d6db8a942a5f /packages/console/core
parent6b019a125a93a9816f9ddec17dc04d2c6e9b4257 (diff)
downloadopencode-e03932e586e89cc30015e6a5006ed5e83881a05c.tar.gz
opencode-e03932e586e89cc30015e6a5006ed5e83881a05c.zip
zen: black usage
Diffstat (limited to 'packages/console/core')
-rw-r--r--packages/console/core/src/billing.ts17
-rw-r--r--packages/console/core/src/black.ts72
2 files changed, 73 insertions, 16 deletions
diff --git a/packages/console/core/src/billing.ts b/packages/console/core/src/billing.ts
index 181055c4e..f052e6fc6 100644
--- a/packages/console/core/src/billing.ts
+++ b/packages/console/core/src/billing.ts
@@ -25,22 +25,7 @@ export namespace Billing {
export const get = async () => {
return Database.use(async (tx) =>
tx
- .select({
- customerID: BillingTable.customerID,
- subscriptionID: BillingTable.subscriptionID,
- paymentMethodID: BillingTable.paymentMethodID,
- paymentMethodType: BillingTable.paymentMethodType,
- paymentMethodLast4: BillingTable.paymentMethodLast4,
- balance: BillingTable.balance,
- reload: BillingTable.reload,
- reloadAmount: BillingTable.reloadAmount,
- reloadTrigger: BillingTable.reloadTrigger,
- monthlyLimit: BillingTable.monthlyLimit,
- monthlyUsage: BillingTable.monthlyUsage,
- timeMonthlyUsageUpdated: BillingTable.timeMonthlyUsageUpdated,
- reloadError: BillingTable.reloadError,
- timeReloadError: BillingTable.timeReloadError,
- })
+ .select()
.from(BillingTable)
.where(eq(BillingTable.workspaceID, Actor.workspace()))
.then((r) => r[0]),
diff --git a/packages/console/core/src/black.ts b/packages/console/core/src/black.ts
index 0ecbc94a4..753d25808 100644
--- a/packages/console/core/src/black.ts
+++ b/packages/console/core/src/black.ts
@@ -1,6 +1,8 @@
import { z } from "zod"
import { fn } from "./util/fn"
import { Resource } from "@opencode-ai/console-resource"
+import { centsToMicroCents } from "./util/price"
+import { getWeekBounds } from "./util/date"
export namespace BlackData {
const Schema = z.object({
@@ -18,3 +20,73 @@ export namespace BlackData {
return Schema.parse(json)
})
}
+
+export namespace Black {
+ export const analyzeRollingUsage = fn(
+ z.object({
+ usage: z.number().int(),
+ timeUpdated: z.date(),
+ }),
+ ({ usage, timeUpdated }) => {
+ const now = new Date()
+ const black = BlackData.get()
+ const rollingWindowMs = black.rollingWindow * 3600 * 1000
+ const rollingLimitInMicroCents = centsToMicroCents(black.rollingLimit * 100)
+ const windowStart = new Date(now.getTime() - rollingWindowMs)
+ if (timeUpdated < windowStart) {
+ return {
+ status: "ok" as const,
+ resetInSec: black.rollingWindow * 3600,
+ usagePercent: 0,
+ }
+ }
+
+ const windowEnd = new Date(timeUpdated.getTime() + rollingWindowMs)
+ if (usage < rollingLimitInMicroCents) {
+ return {
+ status: "ok" as const,
+ resetInSec: Math.ceil((windowEnd.getTime() - now.getTime()) / 1000),
+ usagePercent: Math.ceil(Math.min(100, (usage / rollingLimitInMicroCents) * 100)),
+ }
+ }
+ return {
+ status: "rate-limited" as const,
+ resetInSec: Math.ceil((windowEnd.getTime() - now.getTime()) / 1000),
+ usagePercent: 100,
+ }
+ },
+ )
+
+ export const analyzeWeeklyUsage = fn(
+ z.object({
+ usage: z.number().int(),
+ timeUpdated: z.date(),
+ }),
+ ({ usage, timeUpdated }) => {
+ const black = BlackData.get()
+ const now = new Date()
+ const week = getWeekBounds(now)
+ const fixedLimitInMicroCents = centsToMicroCents(black.fixedLimit * 100)
+ if (timeUpdated < week.start) {
+ return {
+ status: "ok" as const,
+ resetInSec: Math.ceil((week.end.getTime() - now.getTime()) / 1000),
+ usagePercent: 0,
+ }
+ }
+ if (usage < fixedLimitInMicroCents) {
+ return {
+ status: "ok" as const,
+ resetInSec: Math.ceil((week.end.getTime() - now.getTime()) / 1000),
+ usagePercent: Math.ceil(Math.min(100, (usage / fixedLimitInMicroCents) * 100)),
+ }
+ }
+
+ return {
+ status: "rate-limited" as const,
+ resetInSec: Math.ceil((week.end.getTime() - now.getTime()) / 1000),
+ usagePercent: 100,
+ }
+ },
+ )
+}