Compare commits

..
22 Commits
Author SHA1 Message Date
opencode 0c48e6a116 release: v1.0.209
Update Nix Hashes / update (push) Has been cancelled
2025-12-29 23:37:04 +00:00
Adam ef266b2c74 fix(desktop): error page formatting 2025-12-29 17:33:59 -06:00
Aiden Cline 0a1cdc7a58 ci: use .env 2025-12-29 17:31:41 -06:00
Adam 2dec956a17 fix(desktop): better error messages 2025-12-29 17:29:56 -06:00
Aiden Cline ef8388f0ee Revert "feat: read global ~/.claude/skills"
This reverts commit a1c9a1b8c5.
2025-12-29 17:20:04 -06:00
opencode-agent[bot]opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>rekram1-nodeAiden Cline
e5c5b5e872 docs: add run from source guide (#6405)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
2025-12-29 17:12:42 -06:00
Aiden Cline a1c9a1b8c5 feat: read global ~/.claude/skills 2025-12-29 17:11:28 -06:00
Aiden Cline 76b012139a fix: add timeout to filewatcher subscriptions 2025-12-29 16:16:38 -06:00
Aiden Cline 02e5a19242 tweak: adjust git watcher to ignore files other than HEAD 2025-12-29 16:16:38 -06:00
af967648cb docs: opencode notificator plugin (fixed link) (#6341)
Co-authored-by: Ivan Pantic <panta@talentkit.io>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-29 16:03:35 -06:00
Dominik Engelhardt 504a668a26 Set smallOptions for google models on openrouter (#6362) 2025-12-29 16:01:31 -06:00
ja 5efb1c7b2d feat(highlight): add nix syntax highlighting (#6386) 2025-12-29 15:53:41 -06:00
samcornorandSomair Ansar fd973d242e fix(webfetch): make format parameter optional with markdown default (#6345)
Co-authored-by: Somair Ansar <somairansar@Somairs-MacBook-Air.local>
2025-12-29 15:53:12 -06:00
ja c3d8672753 ci: use env vars for DRY workflow config (#6395) 2025-12-29 15:47:47 -06:00
Shoubhit Dash fe8ef041f6 add supermemory plugin to ecosystem (#6399) 2025-12-29 15:46:22 -06:00
Frank c841de947e zen: add gpt 5.1 codex mini 2025-12-29 16:44:11 -05:00
GitHub Action 825dfd48b1 chore: generate 2025-12-29 21:16:16 +00:00
Graham Bennett 923d114ffa Support different Nix store path prefixes (#6367) 2025-12-29 15:15:42 -06:00
Cole Leavitt b157fd10a7 fix: filter messages with only step-start parts in toModelMessage (#6383) 2025-12-29 14:58:11 -06:00
ja 67ebe68160 feat(format): add nixfmt formatter for Nix files (#6380) 2025-12-29 14:57:52 -06:00
GitHub Action 7b63c14154 chore: generate 2025-12-29 20:50:47 +00:00
Adam cdc11cde2e ignore: hide provider connect button until providers loaded 2025-12-29 14:50:06 -06:00
36 changed files with 280 additions and 125 deletions
+6 -3
View File
@@ -5,6 +5,9 @@ on:
- cron: "0 */12 * * *" - cron: "0 */12 * * *"
workflow_dispatch: workflow_dispatch:
env:
LOOKBACK_HOURS: 4
jobs: jobs:
update-docs: update-docs:
if: github.repository == 'sst/opencode' if: github.repository == 'sst/opencode'
@@ -25,9 +28,9 @@ jobs:
- name: Get recent commits - name: Get recent commits
id: commits id: commits
run: | run: |
COMMITS=$(git log --since="4 hours ago" --pretty=format:"- %h %s" 2>/dev/null || echo "") COMMITS=$(git log --since="${{ env.LOOKBACK_HOURS }} hours ago" --pretty=format:"- %h %s" 2>/dev/null || echo "")
if [ -z "$COMMITS" ]; then if [ -z "$COMMITS" ]; then
echo "No commits in the last 4 hours" echo "No commits in the last ${{ env.LOOKBACK_HOURS }} hours"
echo "has_commits=false" >> $GITHUB_OUTPUT echo "has_commits=false" >> $GITHUB_OUTPUT
else else
echo "has_commits=true" >> $GITHUB_OUTPUT echo "has_commits=true" >> $GITHUB_OUTPUT
@@ -47,7 +50,7 @@ jobs:
model: opencode/gpt-5.2 model: opencode/gpt-5.2
agent: docs agent: docs
prompt: | prompt: |
Review the following commits from the last 4 hours and identify any new features that may need documentation. Review the following commits from the last ${{ env.LOOKBACK_HOURS }} hours and identify any new features that may need documentation.
<recent_commits> <recent_commits>
${{ steps.commits.outputs.list }} ${{ steps.commits.outputs.list }}
+9 -5
View File
@@ -5,6 +5,10 @@ on:
- cron: "30 1 * * *" # Daily at 1:30 AM - cron: "30 1 * * *" # Daily at 1:30 AM
workflow_dispatch: workflow_dispatch:
env:
DAYS_BEFORE_STALE: 90
DAYS_BEFORE_CLOSE: 7
jobs: jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -13,17 +17,17 @@ jobs:
steps: steps:
- uses: actions/stale@v10 - uses: actions/stale@v10
with: with:
days-before-stale: 90 days-before-stale: ${{ env.DAYS_BEFORE_STALE }}
days-before-close: 7 days-before-close: ${{ env.DAYS_BEFORE_CLOSE }}
stale-issue-label: "stale" stale-issue-label: "stale"
close-issue-message: | close-issue-message: |
[automated] Closing due to 90+ days of inactivity. [automated] Closing due to ${{ env.DAYS_BEFORE_STALE }}+ days of inactivity.
Feel free to reopen if you still need this! Feel free to reopen if you still need this!
stale-issue-message: | stale-issue-message: |
[automated] This issue has had no activity for 90 days. [automated] This issue has had no activity for ${{ env.DAYS_BEFORE_STALE }} days.
It will be closed in 7 days if there's no new activity. It will be closed in ${{ env.DAYS_BEFORE_CLOSE }} days if there's no new activity.
remove-stale-when-updated: true remove-stale-when-updated: true
exempt-issue-labels: "pinned,security,feature-request,on-hold" exempt-issue-labels: "pinned,security,feature-request,on-hold"
start-date: "2025-12-27" start-date: "2025-12-27"
+4
View File
@@ -20,3 +20,7 @@ opencode.json
a.out a.out
target target
.scripts .scripts
# Local dev files
opencode-dev
logs/
+30
View File
@@ -34,6 +34,36 @@ Want to take on an issue? Leave a comment and a maintainer may assign it to you
bun dev bun dev
``` ```
### Running against a different directory
By default, `bun dev` runs OpenCode in the `packages/opencode` directory. To run it against a different directory or repository:
```bash
bun dev <directory>
```
To run OpenCode in the root of the opencode repo itself:
```bash
bun dev .
```
### Building a "localcode"
To compile a standalone executable:
```bash
./packages/opencode/script/build.ts --single
```
Then run it with:
```bash
./packages/opencode/dist/opencode-<platform>/bin/opencode
```
Replace `<platform>` with your platform (e.g., `darwin-arm64`, `linux-x64`).
- Core pieces: - Core pieces:
- `packages/opencode`: OpenCode core business logic & server. - `packages/opencode`: OpenCode core business logic & server.
- `packages/opencode/src/cli/cmd/tui/`: The TUI code, written in SolidJS with [opentui](https://github.com/sst/opentui) - `packages/opencode/src/cli/cmd/tui/`: The TUI code, written in SolidJS with [opentui](https://github.com/sst/opentui)
+15 -15
View File
@@ -22,7 +22,7 @@
}, },
"packages/app": { "packages/app": {
"name": "@opencode-ai/app", "name": "@opencode-ai/app",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@kobalte/core": "catalog:", "@kobalte/core": "catalog:",
"@opencode-ai/sdk": "workspace:*", "@opencode-ai/sdk": "workspace:*",
@@ -70,7 +70,7 @@
}, },
"packages/console/app": { "packages/console/app": {
"name": "@opencode-ai/console-app", "name": "@opencode-ai/console-app",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@cloudflare/vite-plugin": "1.15.2", "@cloudflare/vite-plugin": "1.15.2",
"@ibm/plex": "6.4.1", "@ibm/plex": "6.4.1",
@@ -98,7 +98,7 @@
}, },
"packages/console/core": { "packages/console/core": {
"name": "@opencode-ai/console-core", "name": "@opencode-ai/console-core",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@aws-sdk/client-sts": "3.782.0", "@aws-sdk/client-sts": "3.782.0",
"@jsx-email/render": "1.1.1", "@jsx-email/render": "1.1.1",
@@ -125,7 +125,7 @@
}, },
"packages/console/function": { "packages/console/function": {
"name": "@opencode-ai/console-function", "name": "@opencode-ai/console-function",
"version": "1.0.208", "version": "1.0.209",
"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",
@@ -149,7 +149,7 @@
}, },
"packages/console/mail": { "packages/console/mail": {
"name": "@opencode-ai/console-mail", "name": "@opencode-ai/console-mail",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@jsx-email/all": "2.2.3", "@jsx-email/all": "2.2.3",
"@jsx-email/cli": "1.4.3", "@jsx-email/cli": "1.4.3",
@@ -173,7 +173,7 @@
}, },
"packages/desktop": { "packages/desktop": {
"name": "@opencode-ai/desktop", "name": "@opencode-ai/desktop",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@opencode-ai/app": "workspace:*", "@opencode-ai/app": "workspace:*",
"@solid-primitives/storage": "catalog:", "@solid-primitives/storage": "catalog:",
@@ -200,7 +200,7 @@
}, },
"packages/enterprise": { "packages/enterprise": {
"name": "@opencode-ai/enterprise", "name": "@opencode-ai/enterprise",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@opencode-ai/ui": "workspace:*", "@opencode-ai/ui": "workspace:*",
"@opencode-ai/util": "workspace:*", "@opencode-ai/util": "workspace:*",
@@ -229,7 +229,7 @@
}, },
"packages/function": { "packages/function": {
"name": "@opencode-ai/function", "name": "@opencode-ai/function",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@octokit/auth-app": "8.0.1", "@octokit/auth-app": "8.0.1",
"@octokit/rest": "catalog:", "@octokit/rest": "catalog:",
@@ -245,7 +245,7 @@
}, },
"packages/opencode": { "packages/opencode": {
"name": "opencode", "name": "opencode",
"version": "1.0.208", "version": "1.0.209",
"bin": { "bin": {
"opencode": "./bin/opencode", "opencode": "./bin/opencode",
}, },
@@ -347,7 +347,7 @@
}, },
"packages/plugin": { "packages/plugin": {
"name": "@opencode-ai/plugin", "name": "@opencode-ai/plugin",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@opencode-ai/sdk": "workspace:*", "@opencode-ai/sdk": "workspace:*",
"zod": "catalog:", "zod": "catalog:",
@@ -367,7 +367,7 @@
}, },
"packages/sdk/js": { "packages/sdk/js": {
"name": "@opencode-ai/sdk", "name": "@opencode-ai/sdk",
"version": "1.0.208", "version": "1.0.209",
"devDependencies": { "devDependencies": {
"@hey-api/openapi-ts": "0.88.1", "@hey-api/openapi-ts": "0.88.1",
"@tsconfig/node22": "catalog:", "@tsconfig/node22": "catalog:",
@@ -378,7 +378,7 @@
}, },
"packages/slack": { "packages/slack": {
"name": "@opencode-ai/slack", "name": "@opencode-ai/slack",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@opencode-ai/sdk": "workspace:*", "@opencode-ai/sdk": "workspace:*",
"@slack/bolt": "^3.17.1", "@slack/bolt": "^3.17.1",
@@ -391,7 +391,7 @@
}, },
"packages/ui": { "packages/ui": {
"name": "@opencode-ai/ui", "name": "@opencode-ai/ui",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@kobalte/core": "catalog:", "@kobalte/core": "catalog:",
"@opencode-ai/sdk": "workspace:*", "@opencode-ai/sdk": "workspace:*",
@@ -429,7 +429,7 @@
}, },
"packages/util": { "packages/util": {
"name": "@opencode-ai/util", "name": "@opencode-ai/util",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"zod": "catalog:", "zod": "catalog:",
}, },
@@ -440,7 +440,7 @@
}, },
"packages/web": { "packages/web": {
"name": "@opencode-ai/web", "name": "@opencode-ai/web",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@astrojs/cloudflare": "12.6.3", "@astrojs/cloudflare": "12.6.3",
"@astrojs/markdown-remark": "6.3.1", "@astrojs/markdown-remark": "6.3.1",
+7 -3
View File
@@ -31,9 +31,13 @@ for (const [name, wasmPath] of byName) {
next = next.replaceAll("tree-sitter.wasm", mainWasm).replaceAll("web-tree-sitter/tree-sitter.wasm", mainWasm) next = next.replaceAll("tree-sitter.wasm", mainWasm).replaceAll("web-tree-sitter/tree-sitter.wasm", mainWasm)
// Collapse any relative prefixes before absolute store paths (e.g., "../../../..//nix/store/...") // Collapse any relative prefixes before absolute store paths (e.g., "../../../..//nix/store/...")
const nixStorePrefix = process.env.NIX_STORE || "/nix/store"
next = next.replace(/(\.\/)+/g, "./") next = next.replace(/(\.\/)+/g, "./")
next = next.replace(/(\.\.\/)+\/?(\/nix\/store[^"']+)/g, "/$2") next = next.replace(
next = next.replace(/(["'])\/{2,}(\/nix\/store[^"']+)(["'])/g, "$1/$2$3") new RegExp(`(\\.\\.\\/)+\\/{1,2}(${nixStorePrefix.replace(/^\//, "").replace(/\//g, "\\/")}[^"']+)`, "g"),
next = next.replace(/(["'])\/\/(nix\/store[^"']+)(["'])/g, "$1/$2$3") "/$2",
)
next = next.replace(new RegExp(`(["'])\\/{2,}(\\/${nixStorePrefix.replace(/\//g, "\\/")}[^"']+)(["'])`, "g"), "$1$2$3")
next = next.replace(new RegExp(`(["'])\\/\\/(${nixStorePrefix.replace(/\//g, "\\/")}[^"']+)(["'])`, "g"), "$1$2$3")
if (next !== content) fs.writeFileSync(file, next) if (next !== content) fs.writeFileSync(file, next)
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@opencode-ai/app", "name": "@opencode-ai/app",
"version": "1.0.208", "version": "1.0.209",
"description": "", "description": "",
"type": "module", "type": "module",
"exports": { "exports": {
+83 -20
View File
@@ -20,11 +20,51 @@ function isInitError(error: unknown): error is InitError {
) )
} }
function safeJson(value: unknown): string {
const seen = new WeakSet<object>()
const json = JSON.stringify(
value,
(_key, val) => {
if (typeof val === "bigint") return val.toString()
if (typeof val === "object" && val) {
if (seen.has(val)) return "[Circular]"
seen.add(val)
}
return val
},
2,
)
return json ?? String(value)
}
function formatInitError(error: InitError): string { function formatInitError(error: InitError): string {
const data = error.data const data = error.data
switch (error.name) { switch (error.name) {
case "MCPFailed": case "MCPFailed":
return `MCP server "${data.name}" failed. Note, opencode does not support MCP authentication yet.` return `MCP server "${data.name}" failed. Note, opencode does not support MCP authentication yet.`
case "ProviderAuthError": {
const providerID = typeof data.providerID === "string" ? data.providerID : "unknown"
const message = typeof data.message === "string" ? data.message : safeJson(data.message)
return `Provider authentication failed (${providerID}): ${message}`
}
case "APIError": {
const message = typeof data.message === "string" ? data.message : "API error"
const lines: string[] = [message]
if (typeof data.statusCode === "number") {
lines.push(`Status: ${data.statusCode}`)
}
if (typeof data.isRetryable === "boolean") {
lines.push(`Retryable: ${data.isRetryable}`)
}
if (typeof data.responseBody === "string" && data.responseBody) {
lines.push(`Response body:\n${data.responseBody}`)
}
return lines.join("\n")
}
case "ProviderModelNotFoundError": { case "ProviderModelNotFoundError": {
const { providerID, modelID, suggestions } = data as { const { providerID, modelID, suggestions } = data as {
providerID: string providerID: string
@@ -37,10 +77,14 @@ function formatInitError(error: InitError): string {
`Check your config (opencode.json) provider/model names`, `Check your config (opencode.json) provider/model names`,
].join("\n") ].join("\n")
} }
case "ProviderInitError": case "ProviderInitError": {
return `Failed to initialize provider "${data.providerID}". Check credentials and configuration.` const providerID = typeof data.providerID === "string" ? data.providerID : "unknown"
case "ConfigJsonError": return `Failed to initialize provider "${providerID}". Check credentials and configuration.`
return `Config file at ${data.path} is not valid JSON(C)` + (data.message ? `: ${data.message}` : "") }
case "ConfigJsonError": {
const message = typeof data.message === "string" ? data.message : ""
return `Config file at ${data.path} is not valid JSON(C)` + (message ? `: ${message}` : "")
}
case "ConfigDirectoryTypoError": case "ConfigDirectoryTypoError":
return `Directory "${data.dir}" in ${data.path} is not valid. Rename the directory to "${data.suggestion}" or remove it. This is a common typo.` return `Directory "${data.dir}" in ${data.path} is not valid. Rename the directory to "${data.suggestion}" or remove it. This is a common typo.`
case "ConfigFrontmatterError": case "ConfigFrontmatterError":
@@ -51,14 +95,14 @@ function formatInitError(error: InitError): string {
(issue: { message: string; path: string[] }) => "↳ " + issue.message + " " + issue.path.join("."), (issue: { message: string; path: string[] }) => "↳ " + issue.message + " " + issue.path.join("."),
) )
: [] : []
return [`Config file at ${data.path} is invalid` + (data.message ? `: ${data.message}` : ""), ...issues].join( const message = typeof data.message === "string" ? data.message : ""
"\n", return [`Config file at ${data.path} is invalid` + (message ? `: ${message}` : ""), ...issues].join("\n")
)
} }
case "UnknownError": case "UnknownError":
return String(data.message) return typeof data.message === "string" ? data.message : safeJson(data)
default: default:
return data.message ? String(data.message) : JSON.stringify(data, null, 2) if (typeof data.message === "string") return data.message
return safeJson(data)
} }
} }
@@ -69,7 +113,7 @@ function formatErrorChain(error: unknown, depth = 0, parentMessage?: string): st
const message = formatInitError(error) const message = formatInitError(error)
if (depth > 0 && parentMessage === message) return "" if (depth > 0 && parentMessage === message) return ""
const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : "" const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : ""
return indent + message return indent + `${error.name}\n${message}`
} }
if (error instanceof Error) { if (error instanceof Error) {
@@ -77,15 +121,34 @@ function formatErrorChain(error: unknown, depth = 0, parentMessage?: string): st
const parts: string[] = [] const parts: string[] = []
const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : "" const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : ""
if (!isDuplicate) { const header = `${error.name}${error.message ? `: ${error.message}` : ""}`
// Stack already includes error name and message, so prefer it const stack = error.stack?.trim()
parts.push(indent + (error.stack ?? `${error.name}: ${error.message}`))
} else if (error.stack) { if (stack) {
// Duplicate message - only show the stack trace lines (skip message) const startsWithHeader = stack.startsWith(header)
const trace = error.stack.split("\n").slice(1).join("\n").trim()
if (trace) { if (isDuplicate && startsWithHeader) {
parts.push(trace) const trace = stack.split("\n").slice(1).join("\n").trim()
if (trace) {
parts.push(indent + trace)
}
} }
if (isDuplicate && !startsWithHeader) {
parts.push(indent + stack)
}
if (!isDuplicate && startsWithHeader) {
parts.push(indent + stack)
}
if (!isDuplicate && !startsWithHeader) {
parts.push(indent + `${header}\n${stack}`)
}
}
if (!stack && !isDuplicate) {
parts.push(indent + header)
} }
if (error.cause) { if (error.cause) {
@@ -105,7 +168,7 @@ function formatErrorChain(error: unknown, depth = 0, parentMessage?: string): st
} }
const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : "" const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : ""
return indent + JSON.stringify(error, null, 2) return indent + safeJson(error)
} }
function formatError(error: unknown): string { function formatError(error: unknown): string {
@@ -131,7 +194,7 @@ export const ErrorPage: Component<ErrorPageProps> = (props) => {
readOnly readOnly
copyable copyable
multiline multiline
class="max-h-96 w-full font-mono text-xs no-scrollbar whitespace-pre" class="max-h-96 w-full font-mono text-xs no-scrollbar"
label="Error Details" label="Error Details"
hideLabel hideLabel
/> />
+2 -2
View File
@@ -916,7 +916,7 @@ export default function Layout(props: ParentProps) {
</div> </div>
<div class="flex flex-col gap-1.5 self-stretch items-start shrink-0 px-2 py-3"> <div class="flex flex-col gap-1.5 self-stretch items-start shrink-0 px-2 py-3">
<Switch> <Switch>
<Match when={!providers.paid().length && expanded()}> <Match when={providers.all().length > 0 && !providers.paid().length && expanded()}>
<div class="rounded-md bg-background-stronger shadow-xs-border-base"> <div class="rounded-md bg-background-stronger shadow-xs-border-base">
<div class="p-3 flex flex-col gap-2"> <div class="p-3 flex flex-col gap-2">
<div class="text-12-medium text-text-strong">Getting started</div> <div class="text-12-medium text-text-strong">Getting started</div>
@@ -935,7 +935,7 @@ export default function Layout(props: ParentProps) {
</Tooltip> </Tooltip>
</div> </div>
</Match> </Match>
<Match when={true}> <Match when={providers.all().length > 0}>
<Tooltip placement="right" value="Connect provider" inactive={expanded()}> <Tooltip placement="right" value="Connect provider" inactive={expanded()}>
<Button <Button
class="flex w-full text-left justify-start text-text-base stroke-[1.5px] rounded-lg px-2" class="flex w-full text-left justify-start text-text-base stroke-[1.5px] rounded-lg px-2"
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@opencode-ai/console-app", "name": "@opencode-ai/console-app",
"version": "1.0.208", "version": "1.0.209",
"type": "module", "type": "module",
"scripts": { "scripts": {
"typecheck": "tsgo --noEmit", "typecheck": "tsgo --noEmit",
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/console-core", "name": "@opencode-ai/console-core",
"version": "1.0.208", "version": "1.0.209",
"private": true, "private": true,
"type": "module", "type": "module",
"dependencies": { "dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@opencode-ai/console-function", "name": "@opencode-ai/console-function",
"version": "1.0.208", "version": "1.0.209",
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"private": true, "private": true,
"type": "module", "type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@opencode-ai/console-mail", "name": "@opencode-ai/console-mail",
"version": "1.0.208", "version": "1.0.209",
"dependencies": { "dependencies": {
"@jsx-email/all": "2.2.3", "@jsx-email/all": "2.2.3",
"@jsx-email/cli": "1.4.3", "@jsx-email/cli": "1.4.3",
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "@opencode-ai/desktop", "name": "@opencode-ai/desktop",
"private": true, "private": true,
"version": "1.0.208", "version": "1.0.209",
"type": "module", "type": "module",
"scripts": { "scripts": {
"typecheck": "tsgo -b", "typecheck": "tsgo -b",
+4
View File
@@ -10,6 +10,10 @@ export default defineConfig({
// //
// 1. prevent Vite from obscuring rust errors // 1. prevent Vite from obscuring rust errors
clearScreen: false, clearScreen: false,
esbuild: {
// Improves production stack traces (less "kQ@..." noise)
keepNames: true,
},
build: { build: {
sourcemap: true, sourcemap: true,
}, },
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@opencode-ai/enterprise", "name": "@opencode-ai/enterprise",
"version": "1.0.208", "version": "1.0.209",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
+6 -6
View File
@@ -1,7 +1,7 @@
id = "opencode" id = "opencode"
name = "OpenCode" name = "OpenCode"
description = "The open source coding agent." description = "The open source coding agent."
version = "1.0.208" version = "1.0.209"
schema_version = 1 schema_version = 1
authors = ["Anomaly"] authors = ["Anomaly"]
repository = "https://github.com/sst/opencode" repository = "https://github.com/sst/opencode"
@@ -11,26 +11,26 @@ name = "OpenCode"
icon = "./icons/opencode.svg" icon = "./icons/opencode.svg"
[agent_servers.opencode.targets.darwin-aarch64] [agent_servers.opencode.targets.darwin-aarch64]
archive = "https://github.com/sst/opencode/releases/download/v1.0.208/opencode-darwin-arm64.zip" archive = "https://github.com/sst/opencode/releases/download/v1.0.209/opencode-darwin-arm64.zip"
cmd = "./opencode" cmd = "./opencode"
args = ["acp"] args = ["acp"]
[agent_servers.opencode.targets.darwin-x86_64] [agent_servers.opencode.targets.darwin-x86_64]
archive = "https://github.com/sst/opencode/releases/download/v1.0.208/opencode-darwin-x64.zip" archive = "https://github.com/sst/opencode/releases/download/v1.0.209/opencode-darwin-x64.zip"
cmd = "./opencode" cmd = "./opencode"
args = ["acp"] args = ["acp"]
[agent_servers.opencode.targets.linux-aarch64] [agent_servers.opencode.targets.linux-aarch64]
archive = "https://github.com/sst/opencode/releases/download/v1.0.208/opencode-linux-arm64.tar.gz" archive = "https://github.com/sst/opencode/releases/download/v1.0.209/opencode-linux-arm64.tar.gz"
cmd = "./opencode" cmd = "./opencode"
args = ["acp"] args = ["acp"]
[agent_servers.opencode.targets.linux-x86_64] [agent_servers.opencode.targets.linux-x86_64]
archive = "https://github.com/sst/opencode/releases/download/v1.0.208/opencode-linux-x64.tar.gz" archive = "https://github.com/sst/opencode/releases/download/v1.0.209/opencode-linux-x64.tar.gz"
cmd = "./opencode" cmd = "./opencode"
args = ["acp"] args = ["acp"]
[agent_servers.opencode.targets.windows-x86_64] [agent_servers.opencode.targets.windows-x86_64]
archive = "https://github.com/sst/opencode/releases/download/v1.0.208/opencode-windows-x64.zip" archive = "https://github.com/sst/opencode/releases/download/v1.0.209/opencode-windows-x64.zip"
cmd = "./opencode.exe" cmd = "./opencode.exe"
args = ["acp"] args = ["acp"]
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@opencode-ai/function", "name": "@opencode-ai/function",
"version": "1.0.208", "version": "1.0.209",
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"private": true, "private": true,
"type": "module", "type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"version": "1.0.208", "version": "1.0.209",
"name": "opencode", "name": "opencode",
"type": "module", "type": "module",
"private": true, "private": true,
+14
View File
@@ -235,5 +235,19 @@ export default {
], ],
}, },
}, },
{
filetype: "nix",
// TODO: Replace with official tree-sitter-nix WASM when published
// See: https://github.com/nix-community/tree-sitter-nix/issues/66
wasm: "https://github.com/ast-grep/ast-grep.github.io/raw/40b84530640aa83a0d34a20a2b0623d7b8e5ea97/website/public/parsers/tree-sitter-nix.wasm",
queries: {
highlights: [
"https://raw.githubusercontent.com/nvim-treesitter/nvim-treesitter/refs/heads/master/queries/nix/highlights.scm",
],
locals: [
"https://raw.githubusercontent.com/nvim-treesitter/nvim-treesitter/refs/heads/master/queries/nix/locals.scm",
],
},
},
], ],
} }
+26 -12
View File
@@ -9,9 +9,13 @@ import path from "path"
// @ts-ignore // @ts-ignore
import { createWrapper } from "@parcel/watcher/wrapper" import { createWrapper } from "@parcel/watcher/wrapper"
import { lazy } from "@/util/lazy" import { lazy } from "@/util/lazy"
import { withTimeout } from "@/util/timeout"
import type ParcelWatcher from "@parcel/watcher" import type ParcelWatcher from "@parcel/watcher"
import { $ } from "bun" import { $ } from "bun"
import { Flag } from "@/flag/flag" import { Flag } from "@/flag/flag"
import { readdir } from "fs/promises"
const SUBSCRIBE_TIMEOUT_MS = 10_000
declare const OPENCODE_LIBC: string | undefined declare const OPENCODE_LIBC: string | undefined
@@ -63,12 +67,16 @@ export namespace FileWatcher {
const cfgIgnores = cfg.watcher?.ignore ?? [] const cfgIgnores = cfg.watcher?.ignore ?? []
if (Flag.OPENCODE_EXPERIMENTAL_FILEWATCHER) { if (Flag.OPENCODE_EXPERIMENTAL_FILEWATCHER) {
subs.push( const pending = watcher().subscribe(Instance.directory, subscribe, {
await watcher().subscribe(Instance.directory, subscribe, { ignore: [...FileIgnore.PATTERNS, ...cfgIgnores],
ignore: [...FileIgnore.PATTERNS, ...cfgIgnores], backend,
backend, })
}), const sub = await withTimeout(pending, SUBSCRIBE_TIMEOUT_MS).catch((err) => {
) log.error("failed to subscribe to Instance.directory", { error: err })
pending.then((s) => s.unsubscribe()).catch(() => {})
return undefined
})
if (sub) subs.push(sub)
} }
const vcsDir = await $`git rev-parse --git-dir` const vcsDir = await $`git rev-parse --git-dir`
@@ -78,12 +86,18 @@ export namespace FileWatcher {
.text() .text()
.then((x) => path.resolve(Instance.worktree, x.trim())) .then((x) => path.resolve(Instance.worktree, x.trim()))
if (vcsDir && !cfgIgnores.includes(".git") && !cfgIgnores.includes(vcsDir)) { if (vcsDir && !cfgIgnores.includes(".git") && !cfgIgnores.includes(vcsDir)) {
subs.push( const gitDirContents = await readdir(vcsDir).catch(() => [])
await watcher().subscribe(vcsDir, subscribe, { const ignoreList = gitDirContents.filter((entry) => entry !== "HEAD")
ignore: ["hooks", "info", "logs", "objects", "refs", "worktrees", "modules", "lfs"], const pending = watcher().subscribe(vcsDir, subscribe, {
backend, ignore: ignoreList,
}), backend,
) })
const sub = await withTimeout(pending, SUBSCRIBE_TIMEOUT_MS).catch((err) => {
log.error("failed to subscribe to vcsDir", { error: err })
pending.then((s) => s.unsubscribe()).catch(() => {})
return undefined
})
if (sub) subs.push(sub)
} }
return { subs } return { subs }
@@ -322,3 +322,12 @@ export const shfmt: Info = {
return Bun.which("shfmt") !== null return Bun.which("shfmt") !== null
}, },
} }
export const nixfmt: Info = {
name: "nixfmt",
command: ["nixfmt", "$FILE"],
extensions: [".nix"],
async enabled() {
return Bun.which("nixfmt") !== null
},
}
+10 -10
View File
@@ -302,22 +302,22 @@ export namespace ProviderTransform {
} }
export function smallOptions(model: Provider.Model) { export function smallOptions(model: Provider.Model) {
const options: Record<string, any> = {}
if (model.providerID === "openai" || model.api.id.includes("gpt-5")) { if (model.providerID === "openai" || model.api.id.includes("gpt-5")) {
if (model.api.id.includes("5.")) { if (model.api.id.includes("5.")) {
options["reasoningEffort"] = "low" return { reasoningEffort: "low" }
} else {
options["reasoningEffort"] = "minimal"
} }
return { reasoningEffort: "minimal" }
} }
if (model.providerID === "google") { if (model.providerID === "google") {
options["thinkingConfig"] = { return { thinkingConfig: { thinkingBudget: 0 } }
thinkingBudget: 0,
}
} }
if (model.providerID === "openrouter") {
return options if (model.api.id.includes("google")) {
return { reasoning: { enabled: false } }
}
return { reasoningEffort: "minimal" }
}
return {}
} }
export function providerOptions(model: Provider.Model, options: { [x: string]: any }) { export function providerOptions(model: Provider.Model, options: { [x: string]: any }) {
+1 -1
View File
@@ -539,7 +539,7 @@ export namespace MessageV2 {
} }
} }
return convertToModelMessages(result.filter((msg) => msg.parts.length > 0)) return convertToModelMessages(result.filter((msg) => msg.parts.some((part) => part.type !== "step-start")))
} }
export const stream = fn(Identifier.schema("session"), async function* (sessionID) { export const stream = fn(Identifier.schema("session"), async function* (sessionID) {
+2 -1
View File
@@ -15,7 +15,8 @@ export const WebFetchTool = Tool.define("webfetch", {
url: z.string().describe("The URL to fetch content from"), url: z.string().describe("The URL to fetch content from"),
format: z format: z
.enum(["text", "markdown", "html"]) .enum(["text", "markdown", "html"])
.describe("The format to return the content in (text, markdown, or html)"), .default("markdown")
.describe("The format to return the content in (text, markdown, or html). Defaults to markdown."),
timeout: z.number().describe("Optional timeout in seconds (max 120)").optional(), timeout: z.number().describe("Optional timeout in seconds (max 120)").optional(),
}), }),
async execute(params, ctx) { async execute(params, ctx) {
+4 -4
View File
@@ -1,13 +1,13 @@
- Fetches content from a specified URL - Fetches content from a specified URL
- Takes a URL and a prompt as input - Takes a URL and optional format as input
- Fetches the URL content, converts HTML to markdown - Fetches the URL content, converts to requested format (markdown by default)
- Returns the model's response about the content - Returns the content in the specified format
- Use this tool when you need to retrieve and analyze web content - Use this tool when you need to retrieve and analyze web content
Usage notes: Usage notes:
- IMPORTANT: if another tool is present that offers better web fetching capabilities, is more targeted to the task, or has fewer restrictions, prefer using that tool instead of this one. - IMPORTANT: if another tool is present that offers better web fetching capabilities, is more targeted to the task, or has fewer restrictions, prefer using that tool instead of this one.
- The URL must be a fully-formed valid URL - The URL must be a fully-formed valid URL
- HTTP URLs will be automatically upgraded to HTTPS - HTTP URLs will be automatically upgraded to HTTPS
- The prompt should describe what information you want to extract from the page - Format options: "markdown" (default), "text", or "html"
- This tool is read-only and does not modify any files - This tool is read-only and does not modify any files
- Results may be summarized if the content is very large - Results may be summarized if the content is very large
+1 -1
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": "1.0.208", "version": "1.0.209",
"type": "module", "type": "module",
"scripts": { "scripts": {
"typecheck": "tsgo --noEmit", "typecheck": "tsgo --noEmit",
+1 -1
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": "1.0.208", "version": "1.0.209",
"type": "module", "type": "module",
"scripts": { "scripts": {
"typecheck": "tsgo --noEmit", "typecheck": "tsgo --noEmit",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@opencode-ai/slack", "name": "@opencode-ai/slack",
"version": "1.0.208", "version": "1.0.209",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "bun run src/index.ts", "dev": "bun run src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@opencode-ai/ui", "name": "@opencode-ai/ui",
"version": "1.0.208", "version": "1.0.209",
"type": "module", "type": "module",
"exports": { "exports": {
"./*": "./src/components/*.tsx", "./*": "./src/components/*.tsx",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@opencode-ai/util", "name": "@opencode-ai/util",
"version": "1.0.208", "version": "1.0.209",
"private": true, "private": true,
"type": "module", "type": "module",
"exports": { "exports": {
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "@opencode-ai/web", "name": "@opencode-ai/web",
"type": "module", "type": "module",
"version": "1.0.208", "version": "1.0.209",
"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",
+2 -1
View File
@@ -32,10 +32,11 @@ You can also check out [awesome-opencode](https://github.com/awesome-opencode/aw
| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Clean up markdown tables produced by LLMs | | [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Clean up markdown tables produced by LLMs |
| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10x faster code editing with Morph Fast Apply API and lazy edit markers | | [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10x faster code editing with Morph Fast Apply API and lazy edit markers |
| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Background agents, pre-built LSP/AST/MCP tools, curated agents, Claude Code compatible | | [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Background agents, pre-built LSP/AST/MCP tools, curated agents, Claude Code compatible |
| [opencode-notificator](https://github.com/panta/opencode-notificator) | Desktop notifications and sound alerts for OpenCode sessions | | [opencode-notificator](https://github.com/panta82/opencode-notificator) | Desktop notifications and sound alerts for OpenCode sessions |
| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Desktop notifications and sound alerts for permission, completion, and error events | | [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Desktop notifications and sound alerts for permission, completion, and error events |
| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | AI-powered automatic Zellij session naming based on OpenCode context | | [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | AI-powered automatic Zellij session naming based on OpenCode context |
| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Allow OpenCode agents to lazy load prompts on demand with skill discovery and injection | | [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Allow OpenCode agents to lazy load prompts on demand with skill discovery and injection |
| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Persistent memory across sessions using Supermemory |
--- ---
+27 -25
View File
@@ -62,31 +62,32 @@ You are charged per request and you can add credits to your account.
You can also access our models through the following API endpoints. You can also access our models through the following API endpoints.
| Model | Model ID | Endpoint | AI SDK Package | | Model | Model ID | Endpoint | AI SDK Package |
| ----------------- | ----------------- | -------------------------------------------------- | --------------------------- | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- |
| GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 Codex | gpt-5.1-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 Codex | gpt-5.1-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 Codex Max | gpt-5.1-codex-max | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 Codex Max | gpt-5.1-codex-max | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 Codex Mini | gpt-5.1-codex-mini | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 Nano | gpt-5-nano | `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.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | GPT 5 Nano | gpt-5-nano | `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 Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | 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 Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Opus 4.5 | claude-opus-4-5 | `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` | | Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| MiniMax M2.1 | minimax-m2.1-free | `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` |
| Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | MiniMax M2.1 | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` |
| GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` |
| GLM 4.7 | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Grok Code Fast 1 | grok-code | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Big Pickle | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Grok Code Fast 1 | grok-code | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Big Pickle | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
The [model id](/docs/config/#models) in your OpenCode config The [model id](/docs/config/#models) in your OpenCode config
uses the format `opencode/<model-id>`. For example, for GPT 5.1 Codex, you would uses the format `opencode/<model-id>`. For example, for GPT 5.1 Codex, you would
@@ -133,6 +134,7 @@ We support a pay-as-you-go model. Below are the prices **per 1M tokens**.
| GPT 5.1 | $1.07 | $8.50 | $0.107 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - |
| GPT 5.1 Codex | $1.07 | $8.50 | $0.107 | - | | GPT 5.1 Codex | $1.07 | $8.50 | $0.107 | - |
| GPT 5.1 Codex Max | $1.25 | $10.00 | $0.125 | - | | GPT 5.1 Codex Max | $1.25 | $10.00 | $0.125 | - |
| GPT 5.1 Codex Mini | $0.25 | $2.00 | $0.025 | - |
| GPT 5 | $1.07 | $8.50 | $0.107 | - | | GPT 5 | $1.07 | $8.50 | $0.107 | - |
| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - | | GPT 5 Codex | $1.07 | $8.50 | $0.107 | - |
| GPT 5 Nano | Free | Free | Free | - | | GPT 5 Nano | Free | Free | Free | - |
+3 -1
View File
@@ -107,7 +107,9 @@ async function main() {
console.log(`📬 Creating pull request...`) console.log(`📬 Creating pull request...`)
const prUrl = const prUrl =
await $`GH_TOKEN=${token} gh pr create --repo ${UPSTREAM_REPO} --base main --head ${FORK_REPO.split("/")[0]}:${branchName} --title "Update ${EXTENSION_NAME} to v${cleanVersion}" --body "Updating OpenCode extension to v${cleanVersion}"`.text() await $`gh pr create --repo ${UPSTREAM_REPO} --base main --head ${FORK_REPO.split("/")[0]}:${branchName} --title "Update ${EXTENSION_NAME} to v${cleanVersion}" --body "Updating OpenCode extension to v${cleanVersion}"`
.env({ GH_TOKEN: token })
.text()
console.log(`✅ Pull request created: ${prUrl}`) console.log(`✅ Pull request created: ${prUrl}`)
console.log(`🎉 Done!`) console.log(`🎉 Done!`)
+1 -1
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": "1.0.208", "version": "1.0.209",
"publisher": "sst-dev", "publisher": "sst-dev",
"repository": { "repository": {
"type": "git", "type": "git",