Merge branch 'dev' into opentui

This commit is contained in:
Dax Raad 2025-09-23 23:47:50 -04:00
commit 0b5730d4dd
26 changed files with 764 additions and 33 deletions

View file

@ -14,7 +14,7 @@
},
"packages/app": {
"name": "@opencode/app",
"version": "0.11.1",
"version": "0.11.3",
"dependencies": {
"@kobalte/core": "0.13.11",
"@opencode-ai/sdk": "workspace:*",
@ -62,7 +62,7 @@
},
"packages/console/core": {
"name": "@opencode/console-core",
"version": "0.11.1",
"version": "0.11.3",
"dependencies": {
"@aws-sdk/client-sts": "3.782.0",
"@opencode/console-resource": "workspace:*",
@ -79,7 +79,7 @@
},
"packages/console/function": {
"name": "@opencode/console-function",
"version": "0.11.1",
"version": "0.11.3",
"dependencies": {
"@ai-sdk/anthropic": "2.0.0",
"@ai-sdk/openai": "2.0.2",
@ -105,7 +105,7 @@
},
"packages/console/scripts": {
"name": "@opencode/console-scripts",
"version": "0.11.1",
"version": "0.11.3",
"dependencies": {
"@opencode/console-core": "workspace:*",
"tsx": "4.20.5",
@ -117,7 +117,7 @@
},
"packages/function": {
"name": "@opencode/function",
"version": "0.11.1",
"version": "0.11.3",
"dependencies": {
"@octokit/auth-app": "8.0.1",
"@octokit/rest": "22.0.0",
@ -132,7 +132,7 @@
},
"packages/opencode": {
"name": "opencode",
"version": "0.11.1",
"version": "0.11.3",
"bin": {
"opencode": "./bin/opencode",
},
@ -191,7 +191,7 @@
},
"packages/plugin": {
"name": "@opencode-ai/plugin",
"version": "0.11.1",
"version": "0.11.3",
"dependencies": {
"@opencode-ai/sdk": "workspace:*",
"zod": "catalog:",
@ -203,7 +203,7 @@
},
"packages/sdk/js": {
"name": "@opencode-ai/sdk",
"version": "0.11.1",
"version": "0.11.3",
"dependencies": {
"@hey-api/openapi-ts": "0.82.5",
},
@ -214,7 +214,7 @@
},
"packages/web": {
"name": "@opencode/web",
"version": "0.11.1",
"version": "0.11.3",
"dependencies": {
"@astrojs/cloudflare": "12.6.3",
"@astrojs/markdown-remark": "6.3.1",

View file

@ -75,6 +75,7 @@ export const stripeWebhook = new WebhookEndpoint("StripeWebhookEndpoint", {
"checkout.session.async_payment_succeeded",
"checkout.session.completed",
"checkout.session.expired",
"charge.refunded",
"customer.created",
"customer.deleted",
"customer.updated",
@ -93,9 +94,6 @@ export const stripeWebhook = new WebhookEndpoint("StripeWebhookEndpoint", {
"customer.subscription.resumed",
"customer.subscription.trial_will_end",
"customer.subscription.updated",
"customer.tax_id.created",
"customer.tax_id.deleted",
"customer.tax_id.updated",
],
})

View file

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

View file

@ -7,7 +7,7 @@
"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",
"start": "vinxi start",
"version": "0.11.1"
"version": "0.11.3"
},
"dependencies": {
"@ibm/plex": "6.4.1",

View file

@ -40,6 +40,10 @@
&[data-slot="payment-amount"] {
color: var(--color-text);
&[data-refunded="true"] {
text-decoration: line-through;
}
}
}

View file

@ -85,7 +85,9 @@ export function PaymentSection() {
{formatDateForTable(date)}
</td>
<td data-slot="payment-id">{payment.id}</td>
<td data-slot="payment-amount">${((payment.amount ?? 0) / 100000000).toFixed(2)}</td>
<td data-slot="payment-amount" data-refunded={!!payment.timeRefunded}>
${((payment.amount ?? 0) / 100000000).toFixed(2)}
</td>
<td data-slot="payment-receipt">
<button
onClick={async () => {

View file

@ -1,6 +1,6 @@
import { Billing } from "@opencode/console-core/billing.js"
import type { APIEvent } from "@solidjs/start/server"
import { Database, eq, sql } from "@opencode/console-core/drizzle/index.js"
import { and, Database, eq, sql } from "@opencode/console-core/drizzle/index.js"
import { BillingTable, PaymentTable } from "@opencode/console-core/schema/billing.sql.js"
import { Identifier } from "@opencode/console-core/identifier.js"
import { centsToMicroCents } from "@opencode/console-core/util/price.js"
@ -91,6 +91,39 @@ export async function POST(input: APIEvent) {
})
})
}
if (body.type === "charge.refunded") {
const customerID = body.data.object.customer as string
const paymentIntentID = body.data.object.payment_intent as string
if (!customerID) throw new Error("Customer ID not found")
if (!paymentIntentID) throw new Error("Payment ID not found")
const workspaceID = await Database.use((tx) =>
tx
.select({
workspaceID: BillingTable.workspaceID,
})
.from(BillingTable)
.where(eq(BillingTable.customerID, customerID))
.then((rows) => rows[0]?.workspaceID),
)
if (!workspaceID) throw new Error("Workspace ID not found")
await Database.transaction(async (tx) => {
await tx
.update(PaymentTable)
.set({
timeRefunded: new Date(body.created * 1000),
})
.where(and(eq(PaymentTable.paymentID, paymentIntentID), eq(PaymentTable.workspaceID, workspaceID)))
await tx
.update(BillingTable)
.set({
balance: sql`${BillingTable.balance} - ${centsToMicroCents(Billing.CHARGE_AMOUNT)}`,
})
.where(eq(BillingTable.workspaceID, workspaceID))
})
}
console.log("finished handling")

View file

@ -0,0 +1 @@
ALTER TABLE `payment` ADD `time_refunded` timestamp(3);

View file

@ -0,0 +1,650 @@
{
"version": "5",
"dialect": "mysql",
"id": "45b67fb4-77ce-4aa2-b883-1971429c69f5",
"prevId": "7f3989cb-3e8b-430e-a0f5-f87051d1d824",
"tables": {
"account": {
"name": "account",
"columns": {
"id": {
"name": "id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"time_created": {
"name": "time_created",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
},
"time_updated": {
"name": "time_updated",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
},
"time_deleted": {
"name": "time_deleted",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"email": {
"name": "email",
"columns": ["email"],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraint": {}
},
"billing": {
"name": "billing",
"columns": {
"id": {
"name": "id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"workspace_id": {
"name": "workspace_id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"time_created": {
"name": "time_created",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
},
"time_updated": {
"name": "time_updated",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
},
"time_deleted": {
"name": "time_deleted",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"customer_id": {
"name": "customer_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"payment_method_id": {
"name": "payment_method_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"payment_method_last4": {
"name": "payment_method_last4",
"type": "varchar(4)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"balance": {
"name": "balance",
"type": "bigint",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"monthly_limit": {
"name": "monthly_limit",
"type": "int",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"monthly_usage": {
"name": "monthly_usage",
"type": "bigint",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"time_monthly_usage_updated": {
"name": "time_monthly_usage_updated",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"reload": {
"name": "reload",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"reload_error": {
"name": "reload_error",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"time_reload_error": {
"name": "time_reload_error",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"time_reload_locked_till": {
"name": "time_reload_locked_till",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"global_customer_id": {
"name": "global_customer_id",
"columns": ["customer_id"],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {
"billing_workspace_id_id_pk": {
"name": "billing_workspace_id_id_pk",
"columns": ["workspace_id", "id"]
}
},
"uniqueConstraints": {},
"checkConstraint": {}
},
"payment": {
"name": "payment",
"columns": {
"id": {
"name": "id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"workspace_id": {
"name": "workspace_id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"time_created": {
"name": "time_created",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
},
"time_updated": {
"name": "time_updated",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
},
"time_deleted": {
"name": "time_deleted",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"customer_id": {
"name": "customer_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"payment_id": {
"name": "payment_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"amount": {
"name": "amount",
"type": "bigint",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"time_refunded": {
"name": "time_refunded",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"payment_workspace_id_id_pk": {
"name": "payment_workspace_id_id_pk",
"columns": ["workspace_id", "id"]
}
},
"uniqueConstraints": {},
"checkConstraint": {}
},
"usage": {
"name": "usage",
"columns": {
"id": {
"name": "id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"workspace_id": {
"name": "workspace_id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"time_created": {
"name": "time_created",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
},
"time_updated": {
"name": "time_updated",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
},
"time_deleted": {
"name": "time_deleted",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"model": {
"name": "model",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"provider": {
"name": "provider",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"input_tokens": {
"name": "input_tokens",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"output_tokens": {
"name": "output_tokens",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"reasoning_tokens": {
"name": "reasoning_tokens",
"type": "int",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"cache_read_tokens": {
"name": "cache_read_tokens",
"type": "int",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"cache_write_5m_tokens": {
"name": "cache_write_5m_tokens",
"type": "int",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"cache_write_1h_tokens": {
"name": "cache_write_1h_tokens",
"type": "int",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"cost": {
"name": "cost",
"type": "bigint",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"usage_workspace_id_id_pk": {
"name": "usage_workspace_id_id_pk",
"columns": ["workspace_id", "id"]
}
},
"uniqueConstraints": {},
"checkConstraint": {}
},
"key": {
"name": "key",
"columns": {
"id": {
"name": "id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"workspace_id": {
"name": "workspace_id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"time_created": {
"name": "time_created",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
},
"time_updated": {
"name": "time_updated",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
},
"time_deleted": {
"name": "time_deleted",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"actor": {
"name": "actor",
"type": "json",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"old_name": {
"name": "old_name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"key": {
"name": "key",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"time_used": {
"name": "time_used",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"global_key": {
"name": "global_key",
"columns": ["key"],
"isUnique": true
},
"name": {
"name": "name",
"columns": ["workspace_id", "name"],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {
"key_workspace_id_id_pk": {
"name": "key_workspace_id_id_pk",
"columns": ["workspace_id", "id"]
}
},
"uniqueConstraints": {},
"checkConstraint": {}
},
"user": {
"name": "user",
"columns": {
"id": {
"name": "id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"workspace_id": {
"name": "workspace_id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"time_created": {
"name": "time_created",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
},
"time_updated": {
"name": "time_updated",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
},
"time_deleted": {
"name": "time_deleted",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"time_seen": {
"name": "time_seen",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"color": {
"name": "color",
"type": "int",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"user_email": {
"name": "user_email",
"columns": ["workspace_id", "email"],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {
"user_workspace_id_id_pk": {
"name": "user_workspace_id_id_pk",
"columns": ["workspace_id", "id"]
}
},
"uniqueConstraints": {},
"checkConstraint": {}
},
"workspace": {
"name": "workspace",
"columns": {
"id": {
"name": "id",
"type": "varchar(30)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"slug": {
"name": "slug",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"time_created": {
"name": "time_created",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
},
"time_updated": {
"name": "time_updated",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"
},
"time_deleted": {
"name": "time_deleted",
"type": "timestamp(3)",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"slug": {
"name": "slug",
"columns": ["slug"],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {
"workspace_id": {
"name": "workspace_id",
"columns": ["id"]
}
},
"uniqueConstraints": {},
"checkConstraint": {}
}
},
"views": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"tables": {},
"indexes": {}
}
}

View file

@ -113,6 +113,13 @@
"when": 1758428484500,
"tag": "0015_cloudy_revanche",
"breakpoints": true
},
{
"idx": 16,
"version": "5",
"when": 1758663086739,
"tag": "0016_cold_la_nuit",
"breakpoints": true
}
]
}

View file

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

View file

@ -30,6 +30,7 @@ export const PaymentTable = mysqlTable(
customerID: varchar("customer_id", { length: 255 }),
paymentID: varchar("payment_id", { length: 255 }),
amount: bigint("amount", { mode: "number" }).notNull(),
timeRefunded: utc("time_refunded"),
},
(table) => [...workspaceIndexes(table)],
)

View file

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

View file

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

View file

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

View file

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

View file

@ -64,6 +64,12 @@ export const RunCommand = cmd({
type: "string",
describe: "agent to use",
})
.option("format", {
type: "string",
choices: ["default", "json"],
default: "default",
describe: "format: default (formatted) or json (raw JSON events)",
})
},
handler: async (args) => {
let message = args.message.join(" ")
@ -144,6 +150,20 @@ export const RunCommand = cmd({
)
}
function outputJsonEvent(type: string, data: any) {
if (args.format === "json") {
const jsonEvent = {
type,
timestamp: Date.now(),
sessionID: session?.id,
...data,
}
process.stdout.write(JSON.stringify(jsonEvent) + "\n")
return true
}
return false
}
let text = ""
Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => {
@ -152,6 +172,7 @@ export const RunCommand = cmd({
const part = evt.properties.part
if (part.type === "tool" && part.state.status === "completed") {
if (outputJsonEvent("tool_use", { part })) return
const [tool, color] = TOOL[part.tool] ?? [part.tool, UI.Style.TEXT_INFO_BOLD]
const title =
part.state.title ||
@ -169,6 +190,7 @@ export const RunCommand = cmd({
text = part.text
if (part.time?.end) {
if (outputJsonEvent("text", { part })) return
UI.empty()
UI.println(UI.markdown(text))
UI.empty()
@ -189,6 +211,7 @@ export const RunCommand = cmd({
}
errorMsg = errorMsg ? errorMsg + "\n" + err : err
if (outputJsonEvent("error", { error })) return
UI.error(err)
})
@ -225,6 +248,7 @@ export const RunCommand = cmd({
const isPiped = !process.stdout.isTTY
if (isPiped) {
const match = result.parts.findLast((x: any) => x.type === "text") as any
if (outputJsonEvent("text", { text: match })) return
if (match) process.stdout.write(UI.markdown(match.text))
if (errorMsg) process.stdout.write(errorMsg)
}

View file

@ -28,7 +28,7 @@ export namespace Plugin {
}
const plugins = [...(config.plugin ?? [])]
if (!Flag.OPENCODE_DISABLE_DEFAULT_PLUGINS) {
plugins.push("opencode-copilot-auth@0.0.2")
plugins.push("opencode-copilot-auth@0.0.3")
plugins.push("opencode-anthropic-auth@0.0.2")
}
for (let plugin of plugins) {

View file

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

View file

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

View file

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

View file

@ -144,6 +144,8 @@ opencode models
This command displays all models available across your configured providers in the format `provider/model`.
This is useful for figuring out the exact model name to use in [your config](/docs/config/).
---
### run

View file

@ -24,9 +24,7 @@ To install opencode on VS Code and popular forks like Cursor, Windsurf, VSCodium
2. Open the integrated terminal
3. Run `opencode` - the extension installs automatically
:::tip
Run Set `export EDITOR="code --wait"` in your terminal to enable `/export` and similar commands. For other editors, check [Editor Setup](https://opencode.ai/docs/tui/#editor-setup).
:::
If on the other hand you want to use your own IDE when you run `/editor` or `/export` from the TUI, you'll need to set `export EDITOR="code --wait"`. [Learn more](/docs/tui/#editor-setup).
---

View file

@ -185,6 +185,9 @@ Redo a previously undone message. Only available after using `/undo`.
Any file changes will also be restored.
:::
Internally, this uses Git to manage the file changes. So your project **needs to
be a Git repository**.
```bash frame="none"
/redo
```
@ -237,6 +240,9 @@ Undo last message in the conversation. Removes the most recent user message, all
Any file changes made will also be reverted.
:::
Internally, this uses Git to manage the file changes. So your project **needs to
be a Git repository**.
```bash frame="none"
/undo
```
@ -266,7 +272,8 @@ Both the `/editor` and `/export` commands use the editor specified in your `EDIT
export EDITOR=nano
export EDITOR=vim
# For GUI editors (VS Code, Cursor, VSCodium, Windsurf, Zed, etc.) include --wait
# For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
# include --wait
export EDITOR="code --wait"
```
@ -279,7 +286,8 @@ Both the `/editor` and `/export` commands use the editor specified in your `EDIT
```bash
set EDITOR=notepad
# For GUI editors (VS Code, Cursor, VSCodium, Windsurf, Zed, etc.) include --wait
# For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
# include --wait
set EDITOR=code --wait
```
@ -292,7 +300,8 @@ Both the `/editor` and `/export` commands use the editor specified in your `EDIT
```powershell
$env:EDITOR = "notepad"
# For GUI editors (VS Code, Cursor, VSCodium, Windsurf, Zed, etc.) include --wait
# For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
# include --wait
$env:EDITOR = "code --wait"
```

View file

@ -64,7 +64,8 @@ You can also access our models through the following API endpoints.
| Model | Mode ID | Endpoint | AI SDK Package |
| ---------------- | ---------------- | --------------------------------------------- | --------------------------- |
| GPT-5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
@ -88,6 +89,7 @@ We support a pay-as-you-go model. Below are the prices **per 1M tokens**.
| Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 |
| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 |
| GPT 5 | $1.25 | $10.00 | $0.125 | - |
| GPT 5 Codex | $1.25 | $10.00 | $0.125 | - |
| Kimi K2 | $0.60 | $2.50 | - | - |
:::note

View file

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