Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
217cf24
fix(desktop): Revert provider icon on select model dialog (#8245)
dbpolito Jan 13, 2026
a70932f
feat: add Undertale and Deltarune built-in themes (#8240)
cmdr-chara Jan 13, 2026
92089bb
chore: generate
actions-user Jan 13, 2026
3600bd2
feat(desktop): Ask Question Tool Support (#8232)
dbpolito Jan 13, 2026
80e1173
fix(mcp): close existing client before reassignment to prevent leaks …
sauerdaniel Jan 13, 2026
b68a4a8
fix(state): delete key from recordsByKey on instance disposal (#8252)
sauerdaniel Jan 13, 2026
5947fe7
docs: document ~/.claude/CLAUDE.md compatibility behavior (#8268)
zeke Jan 13, 2026
05867f9
feat: Add GitLab Duo Agentic Chat Provider Support (#7333)
vglafirov Jan 13, 2026
797a568
fix(cli): mcp auth duplicate radio button icon (#8273)
dmmulroy Jan 13, 2026
1258f7a
Update Nix flake.lock and x86_64-linux hash
actions-user Jan 13, 2026
3a750b0
Update aarch64-darwin hash
actions-user Jan 13, 2026
96ae592
tweak: ensure external dir and bash tool invocations render workdir d…
rekram1-node Jan 13, 2026
33ba064
tweak: external dir permission rendering in tui
rekram1-node Jan 13, 2026
1550ae4
add family to gpt 5.2 codex in codex plugin
rekram1-node Jan 13, 2026
66b7a49
fix(prompt-input): handle Shift+Enter before IME check to prevent stu…
josephbharrison Jan 13, 2026
0a3c72d
feat: add plan mode with enter/exit tools (#8281)
thdxr Jan 13, 2026
3f3816c
chore: generate
actions-user Jan 13, 2026
501347c
test: fix plan agent test path from .opencode/plan/* to .opencode/pla…
thdxr Jan 13, 2026
ec4a440
remove plan
thdxr Jan 13, 2026
774c24e
fix: update User-Agent string to latest Chrome version in webfetch (#…
AlanThiec Jan 13, 2026
452f11f
fix: Add Plugin Mocks to Provider Tests (#8276)
vglafirov Jan 13, 2026
5a309c2
chore: generate
actions-user Jan 13, 2026
0eb898a
tweak: prompt for explore agent better
rekram1-node Jan 13, 2026
0187b6b
do not allow agent to ask custom-less questions
thdxr Jan 13, 2026
3565d8e
release: v1.1.19
Jan 13, 2026
69411bf
refactor(tui): use SDK client for tool list dialog
shuv1337 Jan 14, 2026
e660de4
chore: update lockfile with fork dependencies
shuv1337 Jan 14, 2026
7a9bf58
sync: merge upstream v1.1.19 into integration
shuv1337 Jan 14, 2026
5454765
sync: record last synced tag v1.1.19
shuv1337 Jan 14, 2026
15765ce
merge: incorporate integration release commit
shuv1337 Jan 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/last-synced-tag
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v1.1.18
v1.1.19
99 changes: 84 additions & 15 deletions bun.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions nix/hashes.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"nodeModules": {
"x86_64-linux": "sha256-UCPTTk4b7d2bets7KgCeYBHWAUwUAPUyKm+xDYkSexE=",
"aarch64-darwin": "sha256-Y3o6lovahSWoG9un/l1qxu7hCmIlZXm2LxOLKNiPQfQ="
"x86_64-linux": "sha256-x6A/XT1i3bjakfAj0A1wV4n2s9rpflMDceTeppdP6tE=",
"aarch64-darwin": "sha256-RkamQYbpjJqpHHf76em9lPgeI9k4/kaCf7T+4xHaizY="
}
}
2 changes: 1 addition & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/app",
"version": "1.1.18",
"version": "1.1.19",
"description": "",
"type": "module",
"exports": {
Expand Down
11 changes: 1 addition & 10 deletions packages/app/src/components/dialog-select-model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import { Button } from "@opencode-ai/ui/button"
import { Tag } from "@opencode-ai/ui/tag"
import { Dialog } from "@opencode-ai/ui/dialog"
import { List } from "@opencode-ai/ui/list"
import { ProviderIcon } from "@opencode-ai/ui/provider-icon"
import type { IconName } from "@opencode-ai/ui/icons/provider"
import { DialogSelectProvider } from "./dialog-select-provider"
import { DialogManageModels } from "./dialog-manage-models"

Expand Down Expand Up @@ -37,12 +35,6 @@ const ModelList: Component<{
filterKeys={["provider.name", "name", "id"]}
sortBy={(a, b) => a.name.localeCompare(b.name)}
groupBy={(x) => x.provider.name}
groupHeader={(group) => (
<div class="flex items-center gap-x-3">
<ProviderIcon data-slot="list-item-extra-icon" id={group.items[0].provider.id as IconName} />
<span>{group.category}</span>
</div>
)}
sortGroupsBy={(a, b) => {
if (a.category === "Recent" && b.category !== "Recent") return -1
if (b.category === "Recent" && a.category !== "Recent") return 1
Expand All @@ -60,8 +52,7 @@ const ModelList: Component<{
}}
>
{(i) => (
<div class="w-full flex items-center gap-x-3 pl-1 text-13-regular">
<ProviderIcon data-slot="list-item-extra-icon" id={i.provider.id as IconName} />
<div class="w-full flex items-center gap-x-2 text-13-regular">
<span class="truncate">{i.name}</span>
<Show when={i.provider.id === "opencode" && (!i.cost || i.cost?.input === 0)}>
<Tag>Free</Tag>
Expand Down
20 changes: 15 additions & 5 deletions packages/app/src/components/prompt-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,12 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
if (!isFocused()) setStore("popover", null)
})

// Safety: reset composing state on focus change to prevent stuck state
// This handles edge cases where compositionend event may not fire
createEffect(() => {
if (!isFocused()) setComposing(false)
})

type AtOption = { type: "agent"; name: string; display: string } | { type: "file"; path: string; display: string }

const agentList = createMemo(() =>
Expand Down Expand Up @@ -892,6 +898,14 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
}
}

// Handle Shift+Enter BEFORE IME check - Shift+Enter is never used for IME input
// and should always insert a newline regardless of composition state
if (event.key === "Enter" && event.shiftKey) {
addPart({ type: "text", content: "\n", start: 0, end: 0 })
event.preventDefault()
return
}

if (event.key === "Enter" && isImeComposing(event)) {
return
}
Expand Down Expand Up @@ -955,11 +969,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
return
}

if (event.key === "Enter" && event.shiftKey) {
addPart({ type: "text", content: "\n", start: 0, end: 0 })
event.preventDefault()
return
}
// Note: Shift+Enter is handled earlier, before IME check
if (event.key === "Enter" && !event.shiftKey) {
handleSubmit(event)
}
Expand Down
62 changes: 32 additions & 30 deletions packages/app/src/context/global-sync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,28 +230,28 @@ function createGlobalSync() {
}),
sdk.question.list().then((x) => {
const grouped: Record<string, QuestionRequest[]> = {}
for (const request of x.data ?? []) {
if (!request?.id || !request.sessionID) continue
const existing = grouped[request.sessionID]
for (const question of x.data ?? []) {
if (!question?.id || !question.sessionID) continue
const existing = grouped[question.sessionID]
if (existing) {
existing.push(request)
existing.push(question)
continue
}
grouped[request.sessionID] = [request]
grouped[question.sessionID] = [question]
}

batch(() => {
for (const sessionID of Object.keys(store.question)) {
if (grouped[sessionID]) continue
setStore("question", sessionID, [])
}
for (const [sessionID, requests] of Object.entries(grouped)) {
for (const [sessionID, questions] of Object.entries(grouped)) {
setStore(
"question",
sessionID,
reconcile(
requests
.filter((request) => !!request?.id)
questions
.filter((q) => !!q?.id)
.slice()
.sort((a, b) => a.id.localeCompare(b.id)),
{ key: "id" },
Expand Down Expand Up @@ -448,38 +448,40 @@ function createGlobalSync() {
)
break
}
case "question.replied":
case "question.rejected": {
const requests = store.question[event.properties.sessionID]
if (!requests) break
const result = Binary.search(requests, event.properties.requestID, (r) => r.id)
if (!result.found) break
case "question.asked": {
const sessionID = event.properties.sessionID
const questions = store.question[sessionID]
if (!questions) {
setStore("question", sessionID, [event.properties])
break
}

const result = Binary.search(questions, event.properties.id, (q) => q.id)
if (result.found) {
setStore("question", sessionID, result.index, reconcile(event.properties))
break
}

setStore(
"question",
event.properties.sessionID,
sessionID,
produce((draft) => {
draft.splice(result.index, 1)
draft.splice(result.index, 0, event.properties)
}),
)
break
}
case "question.asked": {
const request = event.properties
const requests = store.question[request.sessionID]
if (!requests) {
setStore("question", request.sessionID, [request])
break
}
const result = Binary.search(requests, request.id, (r) => r.id)
if (result.found) {
setStore("question", request.sessionID, result.index, reconcile(request))
break
}
case "question.replied":
case "question.rejected": {
const questions = store.question[event.properties.sessionID]
if (!questions) break
const result = Binary.search(questions, event.properties.requestID, (q) => q.id)
if (!result.found) break
setStore(
"question",
request.sessionID,
event.properties.sessionID,
produce((draft) => {
draft.splice(result.index, 0, request)
draft.splice(result.index, 1)
}),
)
break
Expand Down
8 changes: 8 additions & 0 deletions packages/app/src/pages/directory-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { LocalProvider } from "@/context/local"
import { base64Decode } from "@opencode-ai/util/encode"
import { DataProvider } from "@opencode-ai/ui/context"
import { iife } from "@opencode-ai/util/iife"
import type { QuestionAnswer } from "@opencode-ai/sdk/v2"

export default function Layout(props: ParentProps) {
const params = useParams()
Expand All @@ -27,6 +28,11 @@ export default function Layout(props: ParentProps) {
response: "once" | "always" | "reject"
}) => sdk.client.permission.respond(input)

const replyToQuestion = (input: { requestID: string; answers: QuestionAnswer[] }) =>
sdk.client.question.reply(input)

const rejectQuestion = (input: { requestID: string }) => sdk.client.question.reject(input)

const navigateToSession = (sessionID: string) => {
navigate(`/${params.dir}/session/${sessionID}`)
}
Expand All @@ -36,6 +42,8 @@ export default function Layout(props: ParentProps) {
data={sync.data}
directory={directory()}
onPermissionRespond={respond}
onQuestionReply={replyToQuestion}
onQuestionReject={rejectQuestion}
onNavigateToSession={navigateToSession}
>
<LocalProvider>{props.children}</LocalProvider>
Expand Down
2 changes: 1 addition & 1 deletion packages/console/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-app",
"version": "1.1.18",
"version": "1.1.19",
"type": "module",
"license": "MIT",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/console/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/console-core",
"version": "1.1.18",
"version": "1.1.19",
"private": true,
"type": "module",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/console/function/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-function",
"version": "1.1.18",
"version": "1.1.19",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion packages/console/mail/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-mail",
"version": "1.1.18",
"version": "1.1.19",
"dependencies": {
"@jsx-email/all": "2.2.3",
"@jsx-email/cli": "1.4.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@shuvcode/desktop",
"private": true,
"version": "1.1.18",
"version": "1.1.19",
"type": "module",
"license": "MIT",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/enterprise/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/enterprise",
"version": "1.1.18",
"version": "1.1.19",
"private": true,
"type": "module",
"license": "MIT",
Expand Down
12 changes: 6 additions & 6 deletions packages/extensions/zed/extension.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
id = "opencode"
name = "OpenCode"
description = "The open source coding agent."
version = "1.1.18"
version = "1.1.19"
schema_version = 1
authors = ["Anomaly"]
repository = "https://github.com/anomalyco/opencode"
Expand All @@ -11,26 +11,26 @@ name = "OpenCode"
icon = "./icons/opencode.svg"

[agent_servers.opencode.targets.darwin-aarch64]
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.18/opencode-darwin-arm64.zip"
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.19/opencode-darwin-arm64.zip"
cmd = "./opencode"
args = ["acp"]

[agent_servers.opencode.targets.darwin-x86_64]
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.18/opencode-darwin-x64.zip"
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.19/opencode-darwin-x64.zip"
cmd = "./opencode"
args = ["acp"]

[agent_servers.opencode.targets.linux-aarch64]
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.18/opencode-linux-arm64.tar.gz"
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.19/opencode-linux-arm64.tar.gz"
cmd = "./opencode"
args = ["acp"]

[agent_servers.opencode.targets.linux-x86_64]
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.18/opencode-linux-x64.tar.gz"
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.19/opencode-linux-x64.tar.gz"
cmd = "./opencode"
args = ["acp"]

[agent_servers.opencode.targets.windows-x86_64]
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.18/opencode-windows-x64.zip"
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.19/opencode-windows-x64.zip"
cmd = "./opencode.exe"
args = ["acp"]
2 changes: 1 addition & 1 deletion packages/function/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/function",
"version": "1.1.18",
"version": "1.1.19",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
Expand Down
3 changes: 2 additions & 1 deletion packages/opencode/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "1.1.18",
"version": "1.1.19",
"name": "opencode",
"type": "module",
"license": "MIT",
Expand Down Expand Up @@ -70,6 +70,7 @@
"@ai-sdk/vercel": "1.0.31",
"@ai-sdk/xai": "2.0.51",
"@clack/prompts": "1.0.0-alpha.1",
"@gitlab/gitlab-ai-provider": "3.1.0",
"@hono/standard-validator": "0.1.5",
"@hono/zod-validator": "catalog:",
"@modelcontextprotocol/sdk": "1.25.2",
Expand Down
6 changes: 5 additions & 1 deletion packages/opencode/src/agent/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export namespace Agent {
[Truncate.GLOB]: "allow",
},
question: "deny",
plan_enter: "deny",
plan_exit: "deny",
// mirrors github.com/github/gitignore Node.gitignore pattern for .env files
read: {
"*": "allow",
Expand All @@ -71,6 +73,7 @@ export namespace Agent {
defaults,
PermissionNext.fromConfig({
question: "allow",
plan_enter: "allow",
}),
user,
),
Expand All @@ -84,9 +87,10 @@ export namespace Agent {
defaults,
PermissionNext.fromConfig({
question: "allow",
plan_exit: "allow",
edit: {
"*": "deny",
".opencode/plan/*.md": "allow",
".opencode/plans/*.md": "allow",
},
}),
user,
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/cli/cmd/mcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function getAuthStatusIcon(status: MCP.AuthStatus): string {
case "expired":
return "⚠"
case "not_authenticated":
return ""
return ""
}
}

Expand Down
Loading