Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c48e6a116 | ||
|
|
ef266b2c74 | ||
|
|
0a1cdc7a58 | ||
|
|
2dec956a17 | ||
|
|
ef8388f0ee | ||
|
|
e5c5b5e872 | ||
|
|
a1c9a1b8c5 | ||
|
|
76b012139a | ||
|
|
02e5a19242 | ||
|
|
af967648cb | ||
|
|
504a668a26 | ||
|
|
5efb1c7b2d | ||
|
|
fd973d242e | ||
|
|
c3d8672753 | ||
|
|
fe8ef041f6 | ||
|
|
c841de947e | ||
|
|
825dfd48b1 | ||
|
|
923d114ffa | ||
|
|
b157fd10a7 | ||
|
|
67ebe68160 | ||
|
|
7b63c14154 | ||
|
|
cdc11cde2e |
@@ -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 }}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -20,3 +20,7 @@ opencode.json
|
|||||||
a.out
|
a.out
|
||||||
target
|
target
|
||||||
.scripts
|
.scripts
|
||||||
|
|
||||||
|
# Local dev files
|
||||||
|
opencode-dev
|
||||||
|
logs/
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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,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": {
|
||||||
|
|||||||
@@ -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
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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,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,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,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,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,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",
|
||||||
|
|||||||
@@ -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,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": {
|
||||||
|
|||||||
@@ -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,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,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,
|
||||||
|
|||||||
@@ -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",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 }) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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,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,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,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,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,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,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",
|
||||||
|
|||||||
@@ -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 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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!`)
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user