([\s\S]*?)<\/highlight>/g
- let match
-
- while ((match = regex.exec(body)) !== null) {
- const source = match[1]
- const content = match[2]
-
- const titleMatch = content.match(/([^<]+)<\/h2>/)
- const pMatch = content.match(/
([^<]+)<\/p>/)
- const imgMatch = content.match(/
({ source, items }))
+type ChangelogRelease = {
+ tag: string
+ name: string
+ date: string
+ url: string
+ highlights: HighlightGroup[]
+ sections: { title: string; items: string[] }[]
}
-function parseMarkdown(body: string) {
- const lines = body.split("\n")
- const sections: { title: string; items: string[] }[] = []
- let current: { title: string; items: string[] } | null = null
- let skip = false
+async function getReleases() {
+ const event = getRequestEvent()
+ const url = event ? new URL("/changelog.json", event.request.url).toString() : "/changelog.json"
- for (const line of lines) {
- if (line.startsWith("## ")) {
- if (current) sections.push(current)
- const title = line.slice(3).trim()
- current = { title, items: [] }
- skip = false
- } else if (line.startsWith("**Thank you")) {
- skip = true
- } else if (line.startsWith("- ") && !skip) {
- current?.items.push(line.slice(2).trim())
- }
- }
- if (current) sections.push(current)
+ const response = await fetch(url).catch(() => undefined)
+ if (!response?.ok) return []
- const highlights = parseHighlights(body)
+ const json = await response.json().catch(() => undefined)
+ return Array.isArray(json?.releases) ? (json.releases as ChangelogRelease[]) : []
+}
- return { sections, highlights }
+function formatDate(dateString: string) {
+ const date = new Date(dateString)
+ return date.toLocaleDateString("en-US", {
+ year: "numeric",
+ month: "short",
+ day: "numeric",
+ })
}
function ReleaseItem(props: { item: string }) {
@@ -217,28 +150,27 @@ export default function Changelog() {
{(release) => {
- const parsed = () => parseMarkdown(release.body || "")
return (
-
+
-
0}>
+ 0}>
- {(group) => }
+ {(group) => }
- 0 && parsed().sections.length > 0}>
-
+ 0 && release.sections.length > 0}>
+
-
-
+
+
{(section) => (
{section.title}
From f48784d1527bb04bda337697c5c1a2a5b991fc75 Mon Sep 17 00:00:00 2001
From: Sebastian Herrlinger
Date: Sun, 25 Jan 2026 13:08:30 -0500
Subject: [PATCH 018/165] upgrade opentui to v0.1.75
---
bun.lock | 20 ++++++++++----------
packages/opencode/package.json | 4 ++--
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/bun.lock b/bun.lock
index d9eeddd61..13647ffa1 100644
--- a/bun.lock
+++ b/bun.lock
@@ -296,8 +296,8 @@
"@opencode-ai/sdk": "workspace:*",
"@opencode-ai/util": "workspace:*",
"@openrouter/ai-sdk-provider": "1.5.2",
- "@opentui/core": "0.1.74",
- "@opentui/solid": "0.1.74",
+ "@opentui/core": "0.1.75",
+ "@opentui/solid": "0.1.75",
"@parcel/watcher": "2.5.1",
"@pierre/diffs": "catalog:",
"@solid-primitives/event-bus": "1.1.2",
@@ -1227,21 +1227,21 @@
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
- "@opentui/core": ["@opentui/core@0.1.74", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.74", "@opentui/core-darwin-x64": "0.1.74", "@opentui/core-linux-arm64": "0.1.74", "@opentui/core-linux-x64": "0.1.74", "@opentui/core-win32-arm64": "0.1.74", "@opentui/core-win32-x64": "0.1.74", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-g4W16ymv12JdgZ+9B4t7mpIICvzWy2+eHERfmDf80ALduOQCUedKQdULcBFhVCYUXIkDRtIy6CID5thMAah3FA=="],
+ "@opentui/core": ["@opentui/core@0.1.75", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.75", "@opentui/core-darwin-x64": "0.1.75", "@opentui/core-linux-arm64": "0.1.75", "@opentui/core-linux-x64": "0.1.75", "@opentui/core-win32-arm64": "0.1.75", "@opentui/core-win32-x64": "0.1.75", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-8ARRZxSG+BXkJmEVtM2DQ4se7DAF1ZCKD07d+AklgTr2mxCzmdxxPbOwRzboSQ6FM7qGuTVPVbV4O2W9DpUmoA=="],
- "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.74", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rfmlDLtm/u17CnuhJgCxPeYMvOST+A2MOdVOk46IurtHO849bdYqK6iudKNlFRs1FOrymgSKF9GlWBHAOKeRjg=="],
+ "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.75", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gGaGZjkFpqcXJk6321JzhRl66pM2VxBlI470L8W4DQUW4S6iDT1R9L7awSzGB4Cn9toUl7DTV8BemaXZYXV4SA=="],
- "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.74", "", { "os": "darwin", "cpu": "x64" }, "sha512-WAD8orsDV0ZdW/5GwjOOB4FY96772xbkz+rcV7WRzEFUVaqoBaC04IuqYzS9d5s+cjkbT5Cpj47hrVYkkVQKng=="],
+ "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.75", "", { "os": "darwin", "cpu": "x64" }, "sha512-tPlvqQI0whZ76amHydpJs5kN+QeWAIcFbI8RAtlAo9baj2EbxTDC+JGwgb9Fnt0/YQx831humbtaNDhV2Jt1bw=="],
- "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.74", "", { "os": "linux", "cpu": "arm64" }, "sha512-lgmHzrzLy4e+rgBS+lhtsMLLgIMLbtLNMm6EzVPyYVDlLDGjM7+ulXMem7AtpaRrWrUUl4REiG9BoQUsCFDwYA=="],
+ "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.75", "", { "os": "linux", "cpu": "arm64" }, "sha512-nVxIQ4Hqf84uBergDpWiVzU6pzpjy6tqBHRQpySxZ2flkJ/U6/aMEizVrQ1jcgIdxZtvqWDETZhzxhG0yDx+cw=="],
- "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.74", "", { "os": "linux", "cpu": "x64" }, "sha512-8Mn2WbdBQ29xCThuPZezjDhd1N3+fXwKkGvCBOdTI0le6h2A/vCNbfUVjwfr/EGZSRXxCG+Yapol34BAULGpOA=="],
+ "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.75", "", { "os": "linux", "cpu": "x64" }, "sha512-1CnApef4kxA+ORyLfbuCLgZfEjp4wr3HjFnt7FAfOb73kIZH82cb7JYixeqRyy9eOcKfKqxLmBYy3o8IDkc4Rg=="],
- "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.74", "", { "os": "win32", "cpu": "arm64" }, "sha512-dvYUXz03avnI6ZluyLp00HPmR0UT/IE/6QS97XBsgJlUTtpnbKkBtB5jD1NHwWkElaRj1Qv2QP36ngFoJqbl9g=="],
+ "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.75", "", { "os": "win32", "cpu": "arm64" }, "sha512-j0UB95nmkYGNzmOrs6GqaddO1S90R0YC6IhbKnbKBdjchFPNVLz9JpexAs6MBDXPZwdKAywMxtwG2h3aTJtxng=="],
- "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.74", "", { "os": "win32", "cpu": "x64" }, "sha512-3wfWXaAKOIlDQz6ZZIESf2M+YGZ7uFHijjTEM8w/STRlLw8Y6+QyGYi1myHSM4d6RSO+/s2EMDxvjDf899W9vQ=="],
+ "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.75", "", { "os": "win32", "cpu": "x64" }, "sha512-ESpVZVGewe3JkB2TwrG3VRbkxT909iPdtvgNT7xTCIYH2VB4jqZomJfvERPTE0tvqAZJm19mHECzJFI8asSJgQ=="],
- "@opentui/solid": ["@opentui/solid@0.1.74", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.74", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-Vz82cI8T9YeJjGsVg4ULp6ral4N+xyt1j9A6Tbu3aaQgEKiB74LW03EXREehfjPr1irOFxtKfWPbx5NKH0Upag=="],
+ "@opentui/solid": ["@opentui/solid@0.1.75", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.75", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-WjKsZIfrm29znfRlcD9w3uUn/+uvoy2MmeoDwTvg1YOa0OjCTCmjZ43L9imp0m9S4HmVU8ma6o2bR4COzcyDdg=="],
"@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="],
diff --git a/packages/opencode/package.json b/packages/opencode/package.json
index 31c9d0ea7..68be07e0c 100644
--- a/packages/opencode/package.json
+++ b/packages/opencode/package.json
@@ -82,8 +82,8 @@
"@opencode-ai/sdk": "workspace:*",
"@opencode-ai/util": "workspace:*",
"@openrouter/ai-sdk-provider": "1.5.2",
- "@opentui/core": "0.1.74",
- "@opentui/solid": "0.1.74",
+ "@opentui/core": "0.1.75",
+ "@opentui/solid": "0.1.75",
"@parcel/watcher": "2.5.1",
"@pierre/diffs": "catalog:",
"@solid-primitives/event-bus": "1.1.2",
From 32a0dcedcbc01243ecc81d4d0144fb22138c3088 Mon Sep 17 00:00:00 2001
From: Github Action
Date: Mon, 26 Jan 2026 16:21:24 +0000
Subject: [PATCH 019/165] chore: update nix node_modules hashes
---
nix/hashes.json | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/nix/hashes.json b/nix/hashes.json
index d5559fdfb..da2f2eaf1 100644
--- a/nix/hashes.json
+++ b/nix/hashes.json
@@ -1,8 +1,8 @@
{
"nodeModules": {
- "x86_64-linux": "sha256-olTZ+tKugAY3LxizsJMlbK3TW78HZUoM03PigvQLP4A=",
- "aarch64-linux": "sha256-xdKDeqMEnYM2+vGySfb8pbcYyo/xMmgxG/ZhPCKaZEg=",
- "aarch64-darwin": "sha256-fihCTrHIiUG+py4vuqdr+YshqSKm2/B5onY50b97sPM=",
- "x86_64-darwin": "sha256-inlQQPNAOdkmKK6HQAMI2bG/ZFlfwmUQu9a6vm6Q0jQ="
+ "x86_64-linux": "sha256-AkI3guNjnE+bLZQVfzm0z14UENOECv2QBqMo5Lzkvt8=",
+ "aarch64-linux": "sha256-dBfdyVTqW+fBZKCxC9Ld+1m3cP+nIbS6UDo0tUfPOSk=",
+ "aarch64-darwin": "sha256-tOw31AMnHkW2cEDi+iqT3P93lU3SiMve26TEIqPz97k=",
+ "x86_64-darwin": "sha256-wL/DmdZmxCmh+r4dsS1XGXuj8VPwR4pUqy5VIA76jl0="
}
}
From 5856ea4e75acdf2910894338561255d53311e4b2 Mon Sep 17 00:00:00 2001
From: Ryan Vogel
Date: Mon, 26 Jan 2026 11:46:56 -0500
Subject: [PATCH 020/165] fix: move changelog footer outside content div to fix
padding (#10712)
---
packages/console/app/src/routes/changelog/index.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/console/app/src/routes/changelog/index.tsx b/packages/console/app/src/routes/changelog/index.tsx
index e05ad42e6..2e2818da5 100644
--- a/packages/console/app/src/routes/changelog/index.tsx
+++ b/packages/console/app/src/routes/changelog/index.tsx
@@ -187,9 +187,9 @@ export default function Changelog() {
}}
-
-
+
+
From 7fcdbd155bf2fe65703a8aad0ac6a72761763405 Mon Sep 17 00:00:00 2001
From: Sam Huckaby
Date: Mon, 26 Jan 2026 11:55:43 -0500
Subject: [PATCH 021/165] fix(app): Order themes alphabetically (#10698)
---
packages/ui/src/theme/default-themes.ts | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/packages/ui/src/theme/default-themes.ts b/packages/ui/src/theme/default-themes.ts
index 88dffeb3f..4d44c3b01 100644
--- a/packages/ui/src/theme/default-themes.ts
+++ b/packages/ui/src/theme/default-themes.ts
@@ -33,18 +33,18 @@ export const auraTheme = auraThemeJson as DesktopTheme
export const DEFAULT_THEMES: Record = {
"oc-1": oc1Theme,
- tokyonight: tokyonightTheme,
- dracula: draculaTheme,
- monokai: monokaiTheme,
- solarized: solarizedTheme,
- nord: nordTheme,
- catppuccin: catppuccinTheme,
+ aura: auraTheme,
ayu: ayuTheme,
+ carbonfox: carbonfoxTheme,
+ catppuccin: catppuccinTheme,
+ dracula: draculaTheme,
+ gruvbox: gruvboxTheme,
+ monokai: monokaiTheme,
+ nightowl: nightowlTheme,
+ nord: nordTheme,
onedarkpro: oneDarkProTheme,
shadesofpurple: shadesOfPurpleTheme,
- nightowl: nightowlTheme,
+ solarized: solarizedTheme,
+ tokyonight: tokyonightTheme,
vesper: vesperTheme,
- carbonfox: carbonfoxTheme,
- gruvbox: gruvboxTheme,
- aura: auraTheme,
}
From 984518b1c0cb74db0b8eb9f77bb15fb97224a4e2 Mon Sep 17 00:00:00 2001
From: Alex Yaroshuk <34632190+alexyaroshuk@users.noreply.github.com>
Date: Tue, 27 Jan 2026 00:57:49 +0800
Subject: [PATCH 022/165] fix(app): restore external link opening in system
browser (#10697)
---
packages/desktop/src/index.tsx | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx
index fe9e3f92e..b0ac83307 100644
--- a/packages/desktop/src/index.tsx
+++ b/packages/desktop/src/index.tsx
@@ -328,18 +328,23 @@ render(() => {
const [serverPassword, setServerPassword] = createSignal(null)
const platform = createPlatform(() => serverPassword())
- function handleClick(e: MouseEvent) {
- const link = (e.target as HTMLElement).closest("a.external-link") as HTMLAnchorElement | null
- if (link?.href) {
- e.preventDefault()
- platform.openLink(link.href)
- }
- }
-
onMount(() => {
- document.addEventListener("click", handleClick)
+ // Handle external links - open in system browser instead of webview
+ const handleClick = (e: MouseEvent) => {
+ const target = e.target as HTMLElement
+ const link = target.closest("a") as HTMLAnchorElement | null
+
+ if (link?.href && !link.href.startsWith("javascript:") && !link.href.startsWith("#")) {
+ e.preventDefault()
+ e.stopPropagation()
+ e.stopImmediatePropagation()
+ void shellOpen(link.href).catch(() => undefined)
+ }
+ }
+
+ document.addEventListener("click", handleClick, true)
onCleanup(() => {
- document.removeEventListener("click", handleClick)
+ document.removeEventListener("click", handleClick, true)
})
})
From 783121c06e388c2d496fd68c59421fdff7d5620f Mon Sep 17 00:00:00 2001
From: Rahul A Mistry <149420892+ProdigyRahul@users.noreply.github.com>
Date: Mon, 26 Jan 2026 22:28:29 +0530
Subject: [PATCH 023/165] fix(ui): use focus-visible instead of focus to
prevent sticky hover effect on click (#10651)
---
packages/app/src/components/session/session-header.tsx | 2 +-
packages/app/src/pages/layout.tsx | 4 ++--
packages/ui/src/components/button.css | 2 +-
packages/ui/src/components/icon-button.css | 4 ++--
packages/ui/src/components/list.css | 4 ++--
packages/ui/src/components/select.css | 2 +-
6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx
index e4a64b339..90daa971d 100644
--- a/packages/app/src/components/session/session-header.tsx
+++ b/packages/app/src/components/session/session-header.tsx
@@ -131,7 +131,7 @@ export function SessionHeader() {