Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/redcode-chat-default.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"opencode": patch
---

Open Redcode directly in the full chat shell, including for profiles that previously selected the legacy interface.
283 changes: 283 additions & 0 deletions .red/researches/2026-08-15-deepseek-harness.md

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions packages/app/e2e/regression/legacy-new-session.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { expect, test } from "@playwright/test"
import { base64Encode } from "@opencode-ai/core/util/encode"
import { mockOpenCodeServer } from "../utils/mock-server"

const draftID = "draft_legacy_new_session"
const directory = "C:/OpenCode/LegacyNewSession"
const server = `http://${process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1"}:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}`

test("redirects a draft to the legacy new-session route", async ({ page }) => {
test("migrates a legacy draft preference into the Redcode chat", async ({ page }) => {
await mockOpenCodeServer(page, {
directory,
project: {
Expand Down Expand Up @@ -35,7 +34,8 @@ test("redirects a draft to the legacy new-session route", async ({ page }) => {

await page.goto(`/new-session?draftId=${draftID}`)

await expect(page).toHaveURL(`/${base64Encode(directory)}/session`)
await expect(page.locator("header[data-tauri-drag-region]")).toBeVisible()
await expect(page.locator('[data-component="prompt-input"]')).toBeVisible()
await expect(page).toHaveURL(`/new-session?draftId=${draftID}`)
await expect(page.locator('[data-slot="redcode-wordmark"]')).toBeVisible()
await expect(page.locator('[data-component="session-draft-timeline"]')).toBeVisible()
await expect(page.locator('[data-component="prompt-input-v2"]')).toBeVisible()
})
2 changes: 1 addition & 1 deletion packages/app/e2e/regression/redcode-entry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ test("opens directly into an unpersisted RedCode chat draft", async ({ page }) =
})
await page.addInitScript(
({ directory }) => {
localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: true } }))
localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: false } }))
localStorage.setItem("opencode-theme-id", "oc-2")
localStorage.setItem("opencode-color-scheme", "dark")
localStorage.setItem(
Expand Down
37 changes: 0 additions & 37 deletions packages/app/e2e/regression/session-timeline-projection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,43 +128,6 @@ test.describe("session timeline projection", () => {
await expect(page.locator('[data-timeline-row="TurnGap"]')).toBeVisible()
})

test("renders comment strips and historical diff summary overflow", async ({ page }) => {
const user = userMessage(
[
userText("The user made the following comment regarding lines 4 through 8 of src/a.ts: Keep this stable", {
id: "prt_comment_only",
synthetic: true,
metadata: {
opencodeComment: {
path: "src/a.ts",
selection: { startLine: 4, startChar: 0, endLine: 8, endChar: 0 },
comment: "Keep this stable",
},
},
}),
userText("Continue after the comment", { id: "prt_comment_visible" }),
],
{ summary: { diffs: Array.from({ length: 11 }, (_, index) => summaryDiff(index)) } },
)
const nextUser = userMessage(undefined, { id: "msg_2000_diff_next_user", created: 1700000010000 })
const nextAssistant = assistantMessage([], {
id: "msg_2001_diff_next_assistant",
parentID: "msg_2000_diff_next_user",
created: 1700000011000,
})
await setupTimeline(page, {
messages: [user, assistantMessage(), nextUser, nextAssistant],
settings: { newLayoutDesigns: false },
})
const scroller = page.locator(".scroll-view__viewport", { has: page.locator("[data-timeline-row]") })
await scroller.evaluate((element) => (element.scrollTop = 0))

await expect(page.locator('[data-timeline-row="CommentStrip"]')).toBeVisible()
await expect(page.getByText("Keep this stable", { exact: true })).toBeVisible()
await expect(page.locator('[data-timeline-row="DiffSummary"]')).toBeVisible()
await expect(page.getByText(/show all/i)).toBeVisible()
})

test("renders interruption independently when the turn is not compacted", async ({ page }) => {
const user = userMessage()
const before = assistantMessage([{ id: "prt_before", type: "text", text: "Before" }], {
Expand Down
4 changes: 2 additions & 2 deletions packages/app/src/context/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ export const sansDefault = "System Sans"
export const terminalDefault = "JetBrainsMono Nerd Font Mono"
const legacyNewLayoutDesignsDefault = import.meta.env.VITE_OPENCODE_CHANNEL !== "prod"
export const newLayoutDesignsDefault = true
// Existing users can switch layouts until local midnight on this date. Set new Date(YYYY, M-1, D) to show.
export const oldInterfaceSunset = new Date(2026, 8, 14)
// Redcode launches directly into the chat shell. Keep the persisted preference only for migration.
export const oldInterfaceSunset = new Date(2026, 7, 15)
const newLayoutDesignsUpgradeCutoff = "1.17.19"

function compareVersions(a: string, b: string) {
Expand Down
Loading