From ee3fd3f7be028471d1f4322c7d2a0072819a8cd0 Mon Sep 17 00:00:00 2001 From: Jay V Date: Thu, 30 Oct 2025 12:40:03 -0400 Subject: ignore:lander --- packages/console/app/src/routes/api/enterprise.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/console/app') diff --git a/packages/console/app/src/routes/api/enterprise.ts b/packages/console/app/src/routes/api/enterprise.ts index 3dc00adb3..e33737d57 100644 --- a/packages/console/app/src/routes/api/enterprise.ts +++ b/packages/console/app/src/routes/api/enterprise.ts @@ -26,7 +26,7 @@ export async function POST(event: APIEvent) { // Create email content const emailContent = ` ${body.message}

--- +--
${body.name}
${body.role}
${body.email}`.trim() -- cgit v1.2.3 From 2a0b67d84f048207d20d952cafa10c430451dc70 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 30 Oct 2025 12:32:25 -0500 Subject: fix: lander space --- .../console/app/src/routes/enterprise/index.tsx | 167 +++++++++++---------- 1 file changed, 84 insertions(+), 83 deletions(-) (limited to 'packages/console/app') diff --git a/packages/console/app/src/routes/enterprise/index.tsx b/packages/console/app/src/routes/enterprise/index.tsx index 5bca6f389..4af0ccce8 100644 --- a/packages/console/app/src/routes/enterprise/index.tsx +++ b/packages/console/app/src/routes/enterprise/index.tsx @@ -65,94 +65,95 @@ export default function Enterprise() {

Your code is yours

OpenCode operates securely inside your organization with no data or context stored - and no licensing restrictions or ownership claims. Start a trial with your team - , then deploy it across your organization by integrating it with your SSO and internal AI gateway. + and no licensing restrictions or ownership claims. Start a trial with your team, + then deploy it across your organization by integrating it with your SSO and + internal AI gateway.

Let us know and how we can help.

-
-
- - - -
- Thanks to OpenCode, we found a way to create software to track all our assets — - even the imaginary ones. -
- - - - - - - - - - - +
+
+ + + +
+ Thanks to OpenCode, we found a way to create software to track all our assets — + even the imaginary ones. +
+ + + + + + + + + + + +
-
-- cgit v1.2.3 From 4f02d7d424bef3d5be7a9bb7a592d4f6d326a8a3 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 30 Oct 2025 14:12:27 -0400 Subject: zen: allow byok requests w/o a balance --- .../console/app/src/routes/zen/util/handler.ts | 84 +++++++++++++++++----- 1 file changed, 66 insertions(+), 18 deletions(-) (limited to 'packages/console/app') diff --git a/packages/console/app/src/routes/zen/util/handler.ts b/packages/console/app/src/routes/zen/util/handler.ts index f7a1f0e16..3163de346 100644 --- a/packages/console/app/src/routes/zen/util/handler.ts +++ b/packages/console/app/src/routes/zen/util/handler.ts @@ -13,7 +13,11 @@ import { ModelTable } from "@opencode-ai/console-core/schema/model.sql.js" import { ProviderTable } from "@opencode-ai/console-core/schema/provider.sql.js" import { logger } from "./logger" import { AuthError, CreditsError, MonthlyLimitError, UserLimitError, ModelError } from "./error" -import { createBodyConverter, createStreamPartConverter, createResponseConverter } from "./provider/provider" +import { + createBodyConverter, + createStreamPartConverter, + createResponseConverter, +} from "./provider/provider" import { Format } from "./format" import { anthropicHelper } from "./provider/anthropic" import { openaiHelper } from "./provider/openai" @@ -43,7 +47,11 @@ export async function handler( }) const zenData = ZenData.list() const modelInfo = validateModel(zenData, body.model) - const providerInfo = selectProvider(zenData, modelInfo, input.request.headers.get("x-real-ip") ?? "") + const providerInfo = selectProvider( + zenData, + modelInfo, + input.request.headers.get("x-real-ip") ?? "", + ) const authInfo = await authenticate(modelInfo, providerInfo) validateBilling(modelInfo, authInfo) validateModelSettings(authInfo) @@ -222,7 +230,11 @@ export async function handler( return { id: modelId, ...modelData } } - function selectProvider(zenData: ZenData, model: Awaited>, ip: string) { + function selectProvider( + zenData: ZenData, + model: Awaited>, + ip: string, + ) { const providers = model.providers .filter((provider) => !provider.disabled) .flatMap((provider) => Array(provider.weight ?? 1).fill(provider)) @@ -239,7 +251,11 @@ export async function handler( return { ...provider, ...zenData.providers[provider.id], - ...(provider.id === "anthropic" ? anthropicHelper : provider.id === "openai" ? openaiHelper : oaCompatHelper), + ...(provider.id === "anthropic" + ? anthropicHelper + : provider.id === "openai" + ? openaiHelper + : oaCompatHelper), } } @@ -279,11 +295,20 @@ export async function handler( .from(KeyTable) .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID)) .innerJoin(BillingTable, eq(BillingTable.workspaceID, KeyTable.workspaceID)) - .innerJoin(UserTable, and(eq(UserTable.workspaceID, KeyTable.workspaceID), eq(UserTable.id, KeyTable.userID))) - .leftJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), eq(ModelTable.model, model.id))) + .innerJoin( + UserTable, + and(eq(UserTable.workspaceID, KeyTable.workspaceID), eq(UserTable.id, KeyTable.userID)), + ) + .leftJoin( + ModelTable, + and(eq(ModelTable.workspaceID, KeyTable.workspaceID), eq(ModelTable.model, model.id)), + ) .leftJoin( ProviderTable, - and(eq(ProviderTable.workspaceID, KeyTable.workspaceID), eq(ProviderTable.provider, providerInfo.id)), + and( + eq(ProviderTable.workspaceID, KeyTable.workspaceID), + eq(ProviderTable.provider, providerInfo.id), + ), ) .where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted))) .then((rows) => rows[0]), @@ -307,12 +332,20 @@ export async function handler( } function validateBilling(model: Model, authInfo: Awaited>) { - if (!authInfo || authInfo.isFree) return + if (!authInfo) return + if (authInfo.provider?.credentials) return + if (authInfo.isFree) return if (model.allowAnonymous) return const billing = authInfo.billing - if (!billing.paymentMethodID) throw new CreditsError("No payment method") - if (billing.balance <= 0) throw new CreditsError("Insufficient balance") + if (!billing.paymentMethodID) + throw new CreditsError( + `No payment method. Add a payment method here: https://opencode.ai/workspace/${authInfo.workspaceID}/billing`, + ) + if (billing.balance <= 0) + throw new CreditsError( + `Insufficient balance. Manage your billing here: https://opencode.ai/workspace/${authInfo.workspaceID}/billing`, + ) const now = new Date() const currentYear = now.getUTCFullYear() @@ -327,7 +360,7 @@ export async function handler( const dateMonth = billing.timeMonthlyUsageUpdated.getUTCMonth() if (currentYear === dateYear && currentMonth === dateMonth) throw new MonthlyLimitError( - `Your workspace has reached its monthly spending limit of $${billing.monthlyLimit}.`, + `Your workspace has reached its monthly spending limit of $${billing.monthlyLimit}. Manage your limits here: https://opencode.ai/workspace/${authInfo.workspaceID}/billing`, ) } @@ -340,7 +373,9 @@ export async function handler( const dateYear = authInfo.user.timeMonthlyUsageUpdated.getUTCFullYear() const dateMonth = authInfo.user.timeMonthlyUsageUpdated.getUTCMonth() if (currentYear === dateYear && currentMonth === dateMonth) - throw new UserLimitError(`You have reached your monthly spending limit of $${authInfo.user.monthlyLimit}.`) + throw new UserLimitError( + `You have reached your monthly spending limit of $${authInfo.user.monthlyLimit}. Manage your limits here: https://opencode.ai/workspace/${authInfo.workspaceID}/members`, + ) } } @@ -364,12 +399,19 @@ export async function handler( providerInfo: Awaited>, usage: any, ) { - const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWrite5mTokens, cacheWrite1hTokens } = - providerInfo.normalizeUsage(usage) + const { + inputTokens, + outputTokens, + reasoningTokens, + cacheReadTokens, + cacheWrite5mTokens, + cacheWrite1hTokens, + } = providerInfo.normalizeUsage(usage) const modelCost = modelInfo.cost200K && - inputTokens + (cacheReadTokens ?? 0) + (cacheWrite5mTokens ?? 0) + (cacheWrite1hTokens ?? 0) > 200_000 + inputTokens + (cacheReadTokens ?? 0) + (cacheWrite5mTokens ?? 0) + (cacheWrite1hTokens ?? 0) > + 200_000 ? modelInfo.cost200K : modelInfo.cost @@ -420,7 +462,8 @@ export async function handler( if (!authInfo) return - const cost = authInfo.isFree || authInfo.provider?.credentials ? 0 : centsToMicroCents(totalCostInCent) + const cost = + authInfo.isFree || authInfo.provider?.credentials ? 0 : centsToMicroCents(totalCostInCent) await Database.transaction(async (tx) => { await tx.insert(UsageTable).values({ workspaceID: authInfo.workspaceID, @@ -460,7 +503,9 @@ export async function handler( `, timeMonthlyUsageUpdated: sql`now()`, }) - .where(and(eq(UserTable.workspaceID, authInfo.workspaceID), eq(UserTable.id, authInfo.user.id))) + .where( + and(eq(UserTable.workspaceID, authInfo.workspaceID), eq(UserTable.id, authInfo.user.id)), + ) }) await Database.use((tx) => @@ -487,7 +532,10 @@ export async function handler( eq(BillingTable.workspaceID, authInfo.workspaceID), eq(BillingTable.reload, true), lt(BillingTable.balance, centsToMicroCents(Billing.CHARGE_THRESHOLD)), - or(isNull(BillingTable.timeReloadLockedTill), lt(BillingTable.timeReloadLockedTill, sql`now()`)), + or( + isNull(BillingTable.timeReloadLockedTill), + lt(BillingTable.timeReloadLockedTill, sql`now()`), + ), ), ), ) -- cgit v1.2.3 From 4dafc532a887287a531f089aa4392be405625418 Mon Sep 17 00:00:00 2001 From: Jay V Date: Thu, 30 Oct 2025 15:47:36 -0400 Subject: ignore: update project stats to reflect current growth --- packages/console/app/src/component/header.tsx | 2 +- packages/console/app/src/routes/index.tsx | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/console/app') diff --git a/packages/console/app/src/component/header.tsx b/packages/console/app/src/component/header.tsx index ea8921f30..e9298df5a 100644 --- a/packages/console/app/src/component/header.tsx +++ b/packages/console/app/src/component/header.tsx @@ -13,7 +13,7 @@ export function Header(props: { zen?: boolean }) { notation: "compact", compactDisplay: "short", }).format(githubData()?.stars!) - : "25K", + : "29K", ) const [store, setStore] = createStore({ diff --git a/packages/console/app/src/routes/index.tsx b/packages/console/app/src/routes/index.tsx index 287c25735..fe6c5698b 100644 --- a/packages/console/app/src/routes/index.tsx +++ b/packages/console/app/src/routes/index.tsx @@ -219,8 +219,8 @@ export default function Home() {
[*]

- With over 26,000 GitHub stars, 188 contributors, and almost{" "} - 3,000 commits, OpenCode is used and trusted by over 200,000{" "} + With over 29,000 GitHub stars, 230 contributors, and almost{" "} + 3,500 commits, OpenCode is used and trusted by over 250,000{" "} developers every month.

@@ -274,7 +274,7 @@ export default function Home() { -
Fig 1.
26K GitHub Stars +
Fig 1.
29K GitHub Stars
@@ -577,7 +577,7 @@ export default function Home() { -
Fig 2.
188 Contributors +
Fig 2.
230 Contributors
@@ -619,7 +619,7 @@ export default function Home() { -
Fig 3.
200K Monthly Devs +
Fig 3.
250K Monthly Devs
-- cgit v1.2.3