Merge branch 'dev' into opentui

This commit is contained in:
Dax Raad 2025-09-20 18:56:16 -04:00
commit 04c8aa1d7c
17 changed files with 70 additions and 55 deletions

View file

@ -84,3 +84,4 @@
| 2025-09-17 | 351,117 (+8,508) | 260,970 (+5,706) | 612,087 (+14,214) | | 2025-09-17 | 351,117 (+8,508) | 260,970 (+5,706) | 612,087 (+14,214) |
| 2025-09-18 | 358,717 (+7,600) | 266,922 (+5,952) | 625,639 (+13,552) | | 2025-09-18 | 358,717 (+7,600) | 266,922 (+5,952) | 625,639 (+13,552) |
| 2025-09-19 | 365,401 (+6,684) | 271,859 (+4,937) | 637,260 (+11,621) | | 2025-09-19 | 365,401 (+6,684) | 271,859 (+4,937) | 637,260 (+11,621) |
| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) |

View file

@ -14,7 +14,7 @@
}, },
"packages/app": { "packages/app": {
"name": "@opencode/app", "name": "@opencode/app",
"version": "0.10.2", "version": "0.10.3",
"dependencies": { "dependencies": {
"@kobalte/core": "0.13.11", "@kobalte/core": "0.13.11",
"@opencode-ai/sdk": "workspace:*", "@opencode-ai/sdk": "workspace:*",
@ -61,7 +61,7 @@
}, },
"packages/console/core": { "packages/console/core": {
"name": "@opencode/console-core", "name": "@opencode/console-core",
"version": "0.10.2", "version": "0.10.3",
"dependencies": { "dependencies": {
"@aws-sdk/client-sts": "3.782.0", "@aws-sdk/client-sts": "3.782.0",
"@opencode/console-resource": "workspace:*", "@opencode/console-resource": "workspace:*",
@ -78,7 +78,7 @@
}, },
"packages/console/function": { "packages/console/function": {
"name": "@opencode/console-function", "name": "@opencode/console-function",
"version": "0.10.2", "version": "0.10.3",
"dependencies": { "dependencies": {
"@ai-sdk/anthropic": "2.0.0", "@ai-sdk/anthropic": "2.0.0",
"@ai-sdk/openai": "2.0.2", "@ai-sdk/openai": "2.0.2",
@ -104,7 +104,7 @@
}, },
"packages/console/scripts": { "packages/console/scripts": {
"name": "@opencode/console-scripts", "name": "@opencode/console-scripts",
"version": "0.10.2", "version": "0.10.3",
"dependencies": { "dependencies": {
"@opencode/console-core": "workspace:*", "@opencode/console-core": "workspace:*",
"tsx": "4.20.5", "tsx": "4.20.5",
@ -116,7 +116,7 @@
}, },
"packages/function": { "packages/function": {
"name": "@opencode/function", "name": "@opencode/function",
"version": "0.10.2", "version": "0.10.3",
"dependencies": { "dependencies": {
"@octokit/auth-app": "8.0.1", "@octokit/auth-app": "8.0.1",
"@octokit/rest": "22.0.0", "@octokit/rest": "22.0.0",
@ -131,7 +131,7 @@
}, },
"packages/opencode": { "packages/opencode": {
"name": "opencode", "name": "opencode",
"version": "0.10.2", "version": "0.10.3",
"bin": { "bin": {
"opencode": "./bin/opencode", "opencode": "./bin/opencode",
}, },
@ -189,7 +189,7 @@
}, },
"packages/plugin": { "packages/plugin": {
"name": "@opencode-ai/plugin", "name": "@opencode-ai/plugin",
"version": "0.10.2", "version": "0.10.3",
"dependencies": { "dependencies": {
"@opencode-ai/sdk": "workspace:*", "@opencode-ai/sdk": "workspace:*",
"zod": "catalog:", "zod": "catalog:",
@ -201,7 +201,7 @@
}, },
"packages/sdk/js": { "packages/sdk/js": {
"name": "@opencode-ai/sdk", "name": "@opencode-ai/sdk",
"version": "0.10.2", "version": "0.10.3",
"dependencies": { "dependencies": {
"@hey-api/openapi-ts": "0.82.5", "@hey-api/openapi-ts": "0.82.5",
}, },
@ -212,7 +212,7 @@
}, },
"packages/web": { "packages/web": {
"name": "@opencode/web", "name": "@opencode/web",
"version": "0.10.2", "version": "0.10.3",
"dependencies": { "dependencies": {
"@astrojs/cloudflare": "12.6.3", "@astrojs/cloudflare": "12.6.3",
"@astrojs/markdown-remark": "6.3.1", "@astrojs/markdown-remark": "6.3.1",

View file

@ -1,6 +1,6 @@
{ {
"name": "@opencode/app", "name": "@opencode/app",
"version": "0.10.2", "version": "0.10.3",
"description": "", "description": "",
"type": "module", "type": "module",
"scripts": { "scripts": {

View file

@ -7,7 +7,7 @@
"dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev", "dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev",
"build": "vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json", "build": "vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json",
"start": "vinxi start", "start": "vinxi start",
"version": "0.10.2" "version": "0.10.3"
}, },
"dependencies": { "dependencies": {
"@ibm/plex": "6.4.1", "@ibm/plex": "6.4.1",

View file

@ -88,6 +88,7 @@ export async function handler(
const authInfo = await authenticate() const authInfo = await authenticate()
const modelInfo = validateModel(body.model, authInfo) const modelInfo = validateModel(body.model, authInfo)
const providerInfo = selectProvider(modelInfo, authInfo) const providerInfo = selectProvider(modelInfo, authInfo)
if (authInfo && !providerInfo.allowAnonymous) validateBilling(authInfo)
logger.metric({ provider: providerInfo.id }) logger.metric({ provider: providerInfo.id })
// Request to model provider // Request to model provider
@ -250,33 +251,43 @@ export async function handler(
}) })
const isFree = FREE_WORKSPACES.includes(data.workspaceID) const isFree = FREE_WORKSPACES.includes(data.workspaceID)
if (!isFree) {
if (!data.paymentMethodID) throw new CreditsError("No payment method")
if (data.balance <= 0) throw new CreditsError("Insufficient balance")
if (
data.monthlyLimit &&
data.monthlyUsage &&
data.timeMonthlyUsageUpdated &&
data.monthlyUsage >= centsToMicroCents(data.monthlyLimit * 100)
) {
const now = new Date()
const currentYear = now.getUTCFullYear()
const currentMonth = now.getUTCMonth()
const dateYear = data.timeMonthlyUsageUpdated.getUTCFullYear()
const dateMonth = data.timeMonthlyUsageUpdated.getUTCMonth()
if (currentYear === dateYear && currentMonth === dateMonth)
throw new MonthlyLimitError(`You have reached your monthly spending limit of $${data.monthlyLimit}.`)
}
}
return { return {
apiKeyId: data.apiKey, apiKeyId: data.apiKey,
workspaceID: data.workspaceID, workspaceID: data.workspaceID,
dataShare: data.dataShare, dataShare: data.dataShare,
billing: {
paymentMethodID: data.paymentMethodID,
balance: data.balance,
monthlyLimit: data.monthlyLimit,
monthlyUsage: data.monthlyUsage,
timeMonthlyUsageUpdated: data.timeMonthlyUsageUpdated,
},
isFree, isFree,
} }
} }
function validateBilling(authInfo: Awaited<ReturnType<typeof authenticate>>) {
if (!authInfo || authInfo.isFree) 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.monthlyLimit &&
billing.monthlyUsage &&
billing.timeMonthlyUsageUpdated &&
billing.monthlyUsage >= centsToMicroCents(billing.monthlyLimit * 100)
) {
const now = new Date()
const currentYear = now.getUTCFullYear()
const currentMonth = now.getUTCMonth()
const dateYear = billing.timeMonthlyUsageUpdated.getUTCFullYear()
const dateMonth = billing.timeMonthlyUsageUpdated.getUTCMonth()
if (currentYear === dateYear && currentMonth === dateMonth)
throw new MonthlyLimitError(`You have reached your monthly spending limit of $${billing.monthlyLimit}.`)
}
}
function validateModel(reqModel: string, authInfo: Awaited<ReturnType<typeof authenticate>>) { function validateModel(reqModel: string, authInfo: Awaited<ReturnType<typeof authenticate>>) {
const json = JSON.parse(Resource.ZEN_MODELS.value) const json = JSON.parse(Resource.ZEN_MODELS.value)

View file

@ -1,7 +1,7 @@
{ {
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"name": "@opencode/console-core", "name": "@opencode/console-core",
"version": "0.10.2", "version": "0.10.3",
"private": true, "private": true,
"type": "module", "type": "module",
"dependencies": { "dependencies": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@opencode/console-function", "name": "@opencode/console-function",
"version": "0.10.2", "version": "0.10.3",
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"private": true, "private": true,
"type": "module", "type": "module",

View file

@ -1,6 +1,6 @@
{ {
"name": "@opencode/console-scripts", "name": "@opencode/console-scripts",
"version": "0.10.2", "version": "0.10.3",
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"private": true, "private": true,
"type": "module", "type": "module",

View file

@ -1,6 +1,6 @@
{ {
"name": "@opencode/function", "name": "@opencode/function",
"version": "0.10.2", "version": "0.10.3",
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"private": true, "private": true,
"type": "module", "type": "module",

View file

@ -1,6 +1,6 @@
{ {
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"version": "0.10.2", "version": "0.10.3",
"name": "opencode", "name": "opencode",
"type": "module", "type": "module",
"private": true, "private": true,

View file

@ -1,7 +1,7 @@
{ {
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/plugin", "name": "@opencode-ai/plugin",
"version": "0.10.2", "version": "0.10.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",

View file

@ -1,7 +1,7 @@
{ {
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/sdk", "name": "@opencode-ai/sdk",
"version": "0.10.2", "version": "0.10.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",

View file

@ -478,9 +478,6 @@ func (m *messagesComponent) renderView() tea.Cmd {
} }
case opencode.AssistantMessage: case opencode.AssistantMessage:
if casted.Summary {
continue
}
if casted.ID == m.app.Session.Revert.MessageID { if casted.ID == m.app.Session.Revert.MessageID {
reverted = true reverted = true
revertedMessageCount = 1 revertedMessageCount = 1

View file

@ -1,7 +1,7 @@
{ {
"name": "@opencode/web", "name": "@opencode/web",
"type": "module", "type": "module",
"version": "0.10.2", "version": "0.10.3",
"scripts": { "scripts": {
"dev": "astro dev", "dev": "astro dev",
"dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",

View file

@ -25,18 +25,18 @@ Without truecolor support, themes may appear with reduced color accuracy or fall
opencode comes with several built-in themes. opencode comes with several built-in themes.
| Name | Description | | Name | Description |
| ------------ | ------------------------------------------ | | ------------ | ---------------------------------------------------------------------------- |
| `system` | Adapts to your terminal's background color | | `system` | Adapts to your terminal's background color |
| `tokyonight` | Based on the Tokyonight theme | | `tokyonight` | Based on the [Tokyonight](https://github.com/folke/tokyonight.nvim) theme |
| `everforest` | Based on the Everforest theme | | `everforest` | Based on the [Everforest](https://github.com/sainnhe/everforest) theme |
| `ayu` | Based on the Ayu dark theme | | `ayu` | Based on the [Ayu](https://github.com/ayu-theme) dark theme |
| `catppuccin` | Based on the Catppuccin theme | | `catppuccin` | Based on the [Catppuccin](https://github.com/catppuccin) theme |
| `gruvbox` | Based on the Gruvbox theme | | `gruvbox` | Based on the [Gruvbox](https://github.com/morhetz/gruvbox) theme |
| `kanagawa` | Based on the Kanagawa theme | | `kanagawa` | Based on the [Kanagawa](https://github.com/rebelot/kanagawa.nvim) theme |
| `nord` | Based on the Nord theme | | `nord` | Based on the [Nord](https://github.com/nordtheme/nord) theme |
| `matrix` | Hacker-style green on black theme | | `matrix` | Hacker-style green on black theme |
| `one-dark` | Based on the Atom One Dark theme | | `one-dark` | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme |
And more, we are constantly adding new themes. And more, we are constantly adding new themes.

View file

@ -81,7 +81,8 @@ We support a pay-as-you-go model. Below are the prices **per 1M tokens**.
| Model | Input | Output | Cached Read | Cached Write | | Model | Input | Output | Cached Read | Cached Write |
| ------------------------------- | ------ | ------ | ----------- | ------------ | | ------------------------------- | ------ | ------ | ----------- | ------------ |
| Qwen3 Coder 480B | $0.45 | $1.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - |
| Grok Code Fast 1 | Free | Free | Free | - | | Grok Code Fast 1 | Free | Free | - | - |
| Code Supernova | Free | Free | - | - |
| Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 |
| Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 |
| Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 |
@ -93,7 +94,10 @@ We support a pay-as-you-go model. Below are the prices **per 1M tokens**.
Credit card fees are passed along at cost; we dont charge anything beyond that. Credit card fees are passed along at cost; we dont charge anything beyond that.
::: :::
Grok Code Fast 1 is currently free on opencode for a limited time. The xAI team is using this time to collect feedback and improve Grok Code. The free models:
- Grok Code Fast 1 is currently free on opencode for a limited time. The xAI team is using this time to collect feedback and improve Grok Code.
- Code Supernova is a stealth model that's free on opencode for a limited time. The team is using this time to collect feedback and improve the model.
:::tip :::tip
Subscription plans and a free tier are coming soon. Subscription plans and a free tier are coming soon.
@ -108,6 +112,8 @@ Subscription plans and a free tier are coming soon.
All our models are hosted in the US. Our providers follow a zero-retention policy and do not use your data for model training, with the following exceptions: All our models are hosted in the US. Our providers follow a zero-retention policy and do not use your data for model training, with the following exceptions:
- Grok Code Fast 1: During its free period, collected data may be used to improve Grok Code. - Grok Code Fast 1: During its free period, collected data may be used to improve Grok Code.
- Code Supernova: During its free period, collected data may be used to improve
the model.
- OpenAI APIs: Requests are retained for 30 days in accordance with [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data). - OpenAI APIs: Requests are retained for 30 days in accordance with [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data).
- Anthropic APIs: Requests are retained for 30 days in accordance with [Anthropic's Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage). - Anthropic APIs: Requests are retained for 30 days in accordance with [Anthropic's Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage).

View file

@ -2,7 +2,7 @@
"name": "opencode", "name": "opencode",
"displayName": "opencode", "displayName": "opencode",
"description": "opencode for VS Code", "description": "opencode for VS Code",
"version": "0.10.2", "version": "0.10.3",
"publisher": "sst-dev", "publisher": "sst-dev",
"repository": { "repository": {
"type": "git", "type": "git",