Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
36ef6cc
fix(ai): finalize Bedrock redacted reasoning at block end (#51999)
rekram1-node Sep 29, 2026
34a8938
fix(ai): bind Bedrock Claude thinking blocks by default (#51959)
rekram1-node Sep 29, 2026
293d60a
chore(desktop): bump electron to 44.4.5 (#52005)
Hona Sep 29, 2026
41d4a9c
fix(session-ui): render moved notice as a timeline divider (#52009)
Hona Sep 29, 2026
a604b7f
fix(ui): calm diff word highlights with @pierre/diffs 1.5.1 (#51236)
Hona Sep 29, 2026
14af33d
fix(ai): show provider error bodies when no message is recognized (#5…
rekram1-node Sep 29, 2026
ff72659
fix(desktop): give isolated dev service a fixed port (#52013)
Hona Sep 29, 2026
2aaa265
fix(ai): read provider error messages from common body layouts (#52014)
rekram1-node Sep 29, 2026
6712cc4
fix(core): turn off Workers AI thinking through the chat template (#5…
rekram1-node Sep 29, 2026
b30c4d0
fix(ai): enable explicit caching on more message protocol routes (#51…
opencode-agent[bot] Sep 29, 2026
d76f968
feat(core): tell users how to sign back in to OpenCode Console (#51847)
vimtor Sep 29, 2026
b29dab3
fix(core): drop SSO link from Console sign-in error (#52062)
vimtor Sep 29, 2026
7ef4a1a
feat(tui): show recently closed tabs in new session menu
kitlangton Sep 29, 2026
0f931d3
chore(core): refresh bundled models.dev snapshot
opencode-agent[bot] Sep 29, 2026
948047a
fix(tui): use disclosure icon for low activity errors (#52097)
opencode-agent[bot] Sep 29, 2026
3126808
fix(ai): defer Mistral thinking metadata until block end (#52008)
rekram1-node Sep 29, 2026
a565ea8
feat(cli): allow disabling the background service (#52107)
opencode-agent[bot] Sep 29, 2026
83fafda
feat(cli): continue run after rejecting a permission ask (#51968)
jlongster Sep 29, 2026
7db941a
docs(console): add GPT 6.1 Sol to model list
fwang Sep 29, 2026
c14a1f5
feat(core): preserve provider response body in session errors (#52136)
rekram1-node Sep 29, 2026
bc5ff1c
fix(cli): answer subagent asks in run and keep parallel rejections co…
jlongster Sep 29, 2026
89d37a0
fix(core): restrict database files to their owner (#52150)
rekram1-node Sep 29, 2026
b694d2b
fix(core): explain ChatGPT token-sharing errors (#52158)
rekram1-node Sep 29, 2026
16ef62c
feat(app): show ChatGPT usage limit dialog (#52153)
rekram1-node Sep 29, 2026
621a5b0
feat(app): show ChatGPT token-sharing guidance (#52160)
rekram1-node Sep 29, 2026
4d90907
feat(core): add separate ChatGPT token-sharing OAuth method (#52147)
rekram1-node Sep 29, 2026
135995d
test: stabilize V2 CI test suites (#52159)
opencode-agent[bot] Sep 29, 2026
4c33a25
feat(cli): add auth export and auth import commands (#52139)
thdxr Sep 29, 2026
0f83038
fix(core): align ChatGPT token sharing with updated partner guide (#5…
rekram1-node Sep 29, 2026
4deda18
fix(app): align ChatGPT usage copy and links (#52163)
rekram1-node Sep 29, 2026
c2a39ac
fix(core): stop promising a ChatGPT usage reset (#52168)
rekram1-node Sep 29, 2026
a2fc196
fix(stats): match document background to page theme (#52169)
opencode-agent[bot] Sep 29, 2026
8d8a7bc
sync release versions for v2.0.20
Sep 29, 2026
cb7efec
chore(sync): merge upstream v2 through v2.0.20
cursoragent Sep 29, 2026
82349b5
test: stub connection status in fork plugin fixtures
cursoragent Sep 29, 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
Prev Previous commit
Next Next commit
fix(ui): calm diff word highlights with @pierre/diffs 1.5.1 (anomalyc…
  • Loading branch information
Hona authored Sep 29, 2026
commit a604b7f773d9807d160bda144150e0b50efd4caf
16 changes: 5 additions & 11 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"@tsconfig/bun": "1.0.9",
"@cloudflare/workers-types": "4.20251008.0",
"@openauthjs/openauth": "0.0.0-20250322224806",
"@pierre/diffs": "1.2.10",
"@pierre/diffs": "1.5.1",
"opentui-spinner": "0.0.7",
"@solid-primitives/event-listener": "2.4.6",
"@solid-primitives/media": "2.3.6",
Expand Down
8 changes: 2 additions & 6 deletions packages/session-ui/component-tests/file.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ for (const split of [false, true]) {
await expect(additions).toHaveText(["select-text"])
await expect(root.locator('[data-line-type="context"] [data-diff-span]')).toHaveCount(0)
await expect(root.locator('[data-line-type="change-deletion"] [data-diff-span]')).toHaveText([
'"http" in',
"? error.reason.",
"response?.",
": undefined",
'"http" in error.reason ? error.reason.http?.response?.headers["x-should-retry"] : undefined',
])
await expect(additions).not.toHaveCSS("background-color", "rgba(0, 0, 0, 0)")
})
Expand All @@ -27,8 +24,7 @@ for (const split of [false, true]) {
const root = await mount("components-session-review--large-file", { args: { split, source } })
const line = root.locator('[data-line][data-line-type="change-addition"]')
await expect(line).toHaveText("export const value = 'after'")
// Plain first paint is not proof that the worker kept inline diffs disabled.
await expect(line.locator('[style*="--syntax-"]')).not.toHaveCount(0)
await expect(line.locator('[style*="--syntax-"]')).toHaveCount(0)
await expect(root.locator("[data-diff-span]")).toHaveCount(0)
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ test("renders large diffs as plain text without changing ordinary highlighting",
await page.goto("/")
await page.waitForFunction(() => !!window.highlighting)
const ordinary = await page.evaluate(() => window.highlighting.mount(1))
expect(ordinary.options).toMatchObject({ lineDiffType: "word-alt", maxLineDiffLength: 1000, tokenizeMaxLineLength: 1000 })
expect(ordinary.options).toMatchObject({ lineDiffType: "word-line", maxLineDiffLength: 1000, tokenizeMaxLineLength: 1000 })
expect(ordinary.syntaxSpans).toBeGreaterThan(0)
await expect(page.locator('[data-line="11"][data-line-type="change-addition"]')).toContainText("status: 201")
})
4 changes: 2 additions & 2 deletions packages/session-ui/performance/highlighting/viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ async function mount(revision: number) {
const offset = messages.length
const start = performance.now()
active = normalize({ ...input, additions: large ? 120 : 12, deletions: large ? 120 : 12 })
const pool = getWorkerPool(large ? "none" : "word-alt")!
const pool = getWorkerPool(large ? "none" : "word-line")!
let firstReady = 0
let rendered = 0
let finish!: (value: Measurement) => void
Expand Down Expand Up @@ -128,7 +128,7 @@ async function mount(revision: number) {

export const highlighting = {
mount,
configure(options: Partial<WorkerRenderingOptions>) { return getWorkerPool(large ? "none" : "word-alt")!.setRenderOptions(options) },
configure(options: Partial<WorkerRenderingOptions>) { return getWorkerPool(large ? "none" : "word-line")!.setRenderOptions(options) },
unmount() { dispose?.(); dispose = undefined; host.scrollTop = 0 },
contents() { return active && { before: text(active, "deletions"), after: text(active, "additions") } },
input: { before, after: inputs.map((input) => input.after) },
Expand Down
15 changes: 7 additions & 8 deletions packages/session-ui/src/components/file-ssr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { acquireVirtualizer, virtualMetrics } from "../pierre/virtualizer"
import { File, type DiffFileProps, type FileProps } from "./file"

type DiffPreload<T> = PreloadMultiFileDiffResult<T> | PreloadFileDiffResult<T>
type DiffPreload<T> = PreloadMultiFileDiffResult<T, undefined> | PreloadFileDiffResult<T, undefined>

type SSRDiffFileProps<T> = DiffFileProps<T> & {
preloadedDiff: DiffPreload<T>
Expand Down Expand Up @@ -119,7 +119,7 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) {
// @ts-expect-error private field required for hydration
fileDiffInstance.fileContainer = fileDiffRef
fileDiffInstance.hydrate(
local.fileDiff
local.fileDiff || !local.before || !local.after
? {
fileDiff: local.fileDiff,
lineAnnotations: annotations,
Expand All @@ -128,12 +128,11 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) {
prerenderedHTML: local.preloadedDiff.prerenderedHTML,
}
: {
oldFile: local.before
? { ...local.before, contents: typeof local.before.contents === "string" ? local.before.contents : "" }
: local.before,
newFile: local.after
? { ...local.after, contents: typeof local.after.contents === "string" ? local.after.contents : "" }
: local.after,
oldFile: {
...local.before,
contents: typeof local.before.contents === "string" ? local.before.contents : "",
},
newFile: { ...local.after, contents: typeof local.after.contents === "string" ? local.after.contents : "" },
lineAnnotations: annotations,
fileContainer: fileDiffRef,
containerWrapper: container,
Expand Down
16 changes: 8 additions & 8 deletions packages/session-ui/src/components/file.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,17 @@ export type FileSearchControl = {
register: (handle: FileSearchHandle | null) => void
}

export type TextFileProps<T = {}> = FileOptions<T> &
export type TextFileProps<T = {}> = FileOptions<T, undefined> &
SharedProps<T> & {
mode: "text"
file: FileContents
annotations?: LineAnnotation<T>[]
preloadedDiff?: PreloadMultiFileDiffResult<T>
preloadedDiff?: PreloadMultiFileDiffResult<T, undefined>
}

type DiffPreload<T> = PreloadMultiFileDiffResult<T> | PreloadFileDiffResult<T>
type DiffPreload<T> = PreloadMultiFileDiffResult<T, undefined> | PreloadFileDiffResult<T, undefined>

type DiffBaseProps<T> = FileDiffOptions<T> &
type DiffBaseProps<T> = FileDiffOptions<T, undefined> &
SharedProps<T> & {
mode: "diff"
annotations?: DiffLineAnnotation<T>[]
Expand Down Expand Up @@ -957,7 +957,7 @@ function DiffViewer<T>(props: DiffFileProps<T>) {
let instance: FileDiff<T> | undefined
let instanceVirtualizer: Virtualizer | undefined
let instanceWorkerPool: ReturnType<typeof getWorkerPool>
let instanceVirtualHunkSeparators: FileDiffOptions<T>["hunkSeparators"] | undefined
let instanceVirtualHunkSeparators: FileDiffOptions<T, undefined>["hunkSeparators"] | undefined
let instanceFileDiff: FileDiffMetadata | undefined
let instanceBefore: FileContents | undefined
let instanceAfter: FileContents | undefined
Expand Down Expand Up @@ -1066,7 +1066,7 @@ function DiffViewer<T>(props: DiffFileProps<T>) {
lineDiffType: "none",
maxLineDiffLength: 0,
tokenizeMaxLineLength: 1,
} satisfies Pick<FileDiffOptions<T>, "lineDiffType" | "maxLineDiffLength" | "tokenizeMaxLineLength">
} satisfies Pick<FileDiffOptions<T, undefined>, "lineDiffType" | "maxLineDiffLength" | "tokenizeMaxLineLength">

const lineCallbacks = createLineCallbacks({
viewer,
Expand All @@ -1076,7 +1076,7 @@ function DiffViewer<T>(props: DiffFileProps<T>) {
onLineNumberSelectionEnd: (range) => local.onLineNumberSelectionEnd?.(range),
})

const options = createMemo<FileDiffOptions<T>>(() => {
const options = createMemo<FileDiffOptions<T, undefined>>(() => {
const base = {
...createDefaultOptions(props.diffStyle),
...others,
Expand Down Expand Up @@ -1112,7 +1112,7 @@ function DiffViewer<T>(props: DiffFileProps<T>) {
createEffect(() => {
const opts = options()
// Worker render options override per-viewer options, including the large-file fallback.
const workerPool = getWorkerPool(large() ? "none" : "word-alt")
const workerPool = getWorkerPool(large() ? "none" : "word-line")
const virtualizer = virtuals.get()
const beforeContents = typeof local.before?.contents === "string" ? local.before.contents : ""
const afterContents = typeof local.after?.contents === "string" ? local.after.contents : ""
Expand Down
6 changes: 3 additions & 3 deletions packages/session-ui/src/components/session-review.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ export type SessionReviewCommentActions = {
export type SessionReviewFocus = { file: string; id: string }

type RawReviewDiff = (PresentationFileDiff | FileDiffInfo) & {
preloaded?: PreloadMultiFileDiffResult<unknown>
preloaded?: PreloadMultiFileDiffResult<unknown, undefined>
}
type ReviewDiff = ((PresentationFileDiff & { file: string }) | FileDiffInfo) & {
preloaded?: PreloadMultiFileDiffResult<unknown>
preloaded?: PreloadMultiFileDiffResult<unknown, undefined>
}
type Item = ViewDiff & { preloaded?: PreloadMultiFileDiffResult<unknown> }
type Item = ViewDiff & { preloaded?: PreloadMultiFileDiffResult<unknown, undefined> }

function diff(value: unknown): value is ReviewDiff {
if (!value || typeof value !== "object" || Array.isArray(value)) return false
Expand Down
2 changes: 1 addition & 1 deletion packages/session-ui/src/context/data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type Data = {
[sessionID: string]: FileDiffInfo[]
}
session_diff_preload?: {
[sessionID: string]: PreloadMultiFileDiffResult<unknown>[]
[sessionID: string]: PreloadMultiFileDiffResult<unknown, undefined>[]
}
}

Expand Down
25 changes: 15 additions & 10 deletions packages/session-ui/src/pierre/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DiffLineAnnotation, FileContents, FileDiffOptions, type SelectedLineRan
import { ComponentProps } from "solid-js"
import { lineCommentStyles } from "../components/line-comment-styles"

export type DiffProps<T = {}> = FileDiffOptions<T> & {
export type DiffProps<T = {}> = FileDiffOptions<T, undefined> & {
before: FileContents
after: FileContents
annotations?: DiffLineAnnotation<T>[]
Expand All @@ -17,6 +17,11 @@ export type DiffProps<T = {}> = FileDiffOptions<T> & {
const unsafeCSS = `
:host {
--diffs-bg: var(--opencode-diffs-bg, var(--color-background-stronger));
/* Pierre mixes 15% in dark mode, which makes collapsed rows read as highlighted. */
--diffs-bg-separator-override: light-dark(
color-mix(in lab, var(--diffs-bg) 98%, var(--diffs-mixer)),
color-mix(in lab, var(--diffs-bg) 95%, var(--diffs-mixer))
);
}
[data-diff],
Expand Down Expand Up @@ -138,15 +143,15 @@ const unsafeCSS = `
}
@media (max-width: 767px) {
/* File annotations share the code column; reclaim the measured number gutter. */
[data-file] [data-line-annotation] {
margin-inline-start: calc(-1 * var(--diffs-column-number-width, 0px));
z-index: 4;
/* File annotations share the code column; reclaim the number gutter. Pierre only measures column widths for
scrolling files with annotations, so derive the gutter from the code grid width instead. */
[data-file][data-overflow='wrap'] [data-code] {
container-type: inline-size;
}
[data-file] [data-annotation-content] {
width: var(--diffs-column-width, auto);
inset-inline-start: 0;
[data-file][data-overflow='wrap'] [data-line-annotation] {
margin-inline-start: calc(100% - 100cqi);
z-index: 4;
}
}
Expand Down Expand Up @@ -198,7 +203,7 @@ ${lineCommentStyles}
`

export function createDefaultOptions<T>(style: FileDiffOptions<T>["diffStyle"]) {
export function createDefaultOptions<T>(style: FileDiffOptions<T, undefined>["diffStyle"]) {
return {
theme: "OpenCode",
themeType: "system",
Expand All @@ -210,7 +215,7 @@ export function createDefaultOptions<T>(style: FileDiffOptions<T>["diffStyle"])
disableBackground: false,
expansionLineCount: 20,
hunkSeparators: "line-info-basic",
lineDiffType: "word-alt",
lineDiffType: "word-line",
maxLineDiffLength: 1000,
maxLineLengthForHighlighting: 1000,
disableFileHeader: true,
Expand Down
6 changes: 3 additions & 3 deletions packages/session-ui/src/pierre/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function workerFactory(): Worker {
return new Worker(ShikiWorkerUrl, { type: "module" })
}

function createPool(lineDiffType: "none" | "word-alt") {
function createPool(lineDiffType: "none" | "word-line") {
const pool = new WorkerPoolManager(
{
workerFactory,
Expand Down Expand Up @@ -36,15 +36,15 @@ function createPool(lineDiffType: "none" | "word-alt") {
let plain: WorkerPoolManager | undefined
let diff: WorkerPoolManager | undefined

export function getWorkerPool(lineDiffType: "none" | "word-alt" = "word-alt"): WorkerPoolManager | undefined {
export function getWorkerPool(lineDiffType: "none" | "word-line" = "word-line"): WorkerPoolManager | undefined {
if (typeof window === "undefined") return

if (lineDiffType === "none") {
if (!plain) plain = createPool("none")
return plain
}

if (!diff) diff = createPool("word-alt")
if (!diff) diff = createPool("word-line")
return diff
}

Expand Down