Skip to content

Commit bd6c541

Browse files
authored
Merge branch 'opentui' into bug-fix/3322-web-and-tui-report-token-usage-differently
2 parents 1a2ec7f + 941ba7f commit bd6c541

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+3602
-1614
lines changed

STATS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,4 @@
117117
| 2025-10-21 | 548,721 (+7,457) | 479,703 (+6,751) | 1,028,424 (+14,208) |
118118
| 2025-10-22 | 557,949 (+9,228) | 491,395 (+11,692) | 1,049,344 (+20,920) |
119119
| 2025-10-23 | 564,716 (+6,767) | 498,736 (+7,341) | 1,063,452 (+14,108) |
120+
| 2025-10-24 | 572,692 (+7,976) | 506,905 (+8,169) | 1,079,597 (+16,145) |

bun.lock

Lines changed: 49 additions & 44 deletions
Large diffs are not rendered by default.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"type": "module",
77
"packageManager": "bun@1.3.0",
88
"scripts": {
9-
"dev": "bun run --cwd packages/opencode src/index.ts",
9+
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
1010
"typecheck": "bun turbo typecheck",
1111
"prepare": "husky",
1212
"random": "echo 'Random script'"
@@ -28,6 +28,7 @@
2828
"@tsconfig/bun": "1.0.9",
2929
"@cloudflare/workers-types": "4.20251008.0",
3030
"@openauthjs/openauth": "0.0.0-20250322224806",
31+
"@pierre/precision-diffs": "0.0.2-alpha.1-1",
3132
"@solidjs/meta": "0.29.4",
3233
"@tailwindcss/vite": "4.1.11",
3334
"diff": "8.0.2",

packages/console/app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev",
88
"build": "vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json",
99
"start": "vinxi start",
10-
"version": "0.15.14"
10+
"version": "0.15.16"
1111
},
1212
"dependencies": {
1313
"@ibm/plex": "6.4.1",

packages/console/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://json.schemastore.org/package.json",
33
"name": "@opencode-ai/console-core",
4-
"version": "0.15.14",
4+
"version": "0.15.16",
55
"private": true,
66
"type": "module",
77
"dependencies": {

packages/console/function/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opencode-ai/console-function",
3-
"version": "0.15.14",
3+
"version": "0.15.16",
44
"$schema": "https://json.schemastore.org/package.json",
55
"private": true,
66
"type": "module",

packages/console/mail/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opencode-ai/console-mail",
3-
"version": "0.15.14",
3+
"version": "0.15.16",
44
"dependencies": {
55
"@jsx-email/all": "2.2.3",
66
"@jsx-email/cli": "1.4.3",

packages/desktop/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opencode-ai/desktop",
3-
"version": "0.15.14",
3+
"version": "0.15.16",
44
"description": "",
55
"type": "module",
66
"scripts": {
@@ -26,6 +26,7 @@
2626
"@kobalte/core": "catalog:",
2727
"@opencode-ai/sdk": "workspace:*",
2828
"@opencode-ai/ui": "workspace:*",
29+
"@pierre/precision-diffs": "catalog:",
2930
"@shikijs/transformers": "3.9.2",
3031
"@solid-primitives/active-element": "2.1.3",
3132
"@solid-primitives/event-bus": "1.1.2",

packages/desktop/src/components/code.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { bundledLanguages, type BundledLanguage, type ShikiTransformer } from "shiki"
22
import { splitProps, type ComponentProps, createEffect, onMount, onCleanup, createMemo, createResource } from "solid-js"
3-
import { useLocal, useShiki } from "@/context"
4-
import type { TextSelection } from "@/context/local"
3+
import { useLocal, type TextSelection } from "@/context/local"
54
import { getFileExtension, getNodeOffsetInLine, getSelectionInContainer } from "@/utils"
5+
import { useShiki } from "@/context/shiki"
66

77
type DefinedSelection = Exclude<TextSelection, undefined>
88

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import {
2+
type FileContents,
3+
FileDiff,
4+
type DiffLineAnnotation,
5+
DiffFileRendererOptions,
6+
registerCustomTheme,
7+
} from "@pierre/precision-diffs"
8+
import { ComponentProps, createEffect, splitProps } from "solid-js"
9+
10+
export type DiffProps<T = {}> = Omit<DiffFileRendererOptions<T>, "themes"> & {
11+
before: FileContents
12+
after: FileContents
13+
annotations?: DiffLineAnnotation<T>[]
14+
class?: string
15+
classList?: ComponentProps<"div">["classList"]
16+
}
17+
18+
// @ts-expect-error
19+
registerCustomTheme("opencode", () => import("./theme.json"))
20+
21+
// interface ThreadMetadata {
22+
// threadId: string
23+
// }
24+
25+
export function Diff<T>(props: DiffProps<T>) {
26+
let container!: HTMLDivElement
27+
const [local, others] = splitProps(props, ["before", "after", "class", "classList", "annotations"])
28+
29+
// const lineAnnotations: DiffLineAnnotation<ThreadMetadata>[] = [
30+
// {
31+
// side: "additions",
32+
// // The line number specified for an annotation is the visual line number
33+
// // you see in the number column of a diff
34+
// lineNumber: 16,
35+
// metadata: { threadId: "68b329da9893e34099c7d8ad5cb9c940" },
36+
// },
37+
// ]
38+
39+
// If you ever want to update the options for an instance, simple call
40+
// 'setOptions' with the new options. Bear in mind, this does NOT merge
41+
// existing properties, it's a full replace
42+
// instance.setOptions({
43+
// ...instance.options,
44+
// theme: "pierre-dark",
45+
// themes: undefined,
46+
// })
47+
48+
// When ready to render, simply call .render with old/new file, optional
49+
// annotations and a container element to hold the diff
50+
createEffect(() => {
51+
const instance = new FileDiff<T>({
52+
theme: "opencode",
53+
// Or can also provide a 'themes' prop, which allows the code to adapt
54+
// to your OS light or dark theme
55+
// themes: { dark: 'pierre-night', light: 'pierre-light' },
56+
// When using the 'themes' prop, 'themeType' allows you to force 'dark'
57+
// or 'light' theme, or inherit from the OS ('system') theme.
58+
themeType: "system",
59+
// Disable the line numbers for your diffs, generally not recommended
60+
disableLineNumbers: false,
61+
// Whether code should 'wrap' with long lines or 'scroll'.
62+
overflow: "scroll",
63+
// Normally you shouldn't need this prop, but if you don't provide a
64+
// valid filename or your file doesn't have an extension you may want to
65+
// override the automatic detection. You can specify that language here:
66+
// https://shiki.style/languages
67+
// lang?: SupportedLanguages;
68+
// 'diffStyle' controls whether the diff is presented side by side or
69+
// in a unified (single column) view
70+
diffStyle: "unified",
71+
// Line decorators to help highlight changes.
72+
// 'bars' (default):
73+
// Shows some red-ish or green-ish (theme dependent) bars on the left
74+
// edge of relevant lines
75+
//
76+
// 'classic':
77+
// shows '+' characters on additions and '-' characters on deletions
78+
//
79+
// 'none':
80+
// No special diff indicators are shown
81+
diffIndicators: "bars",
82+
// By default green-ish or red-ish background are shown on added and
83+
// deleted lines respectively. Disable that feature here
84+
disableBackground: false,
85+
// Diffs are split up into hunks, this setting customizes what to show
86+
// between each hunk.
87+
//
88+
// 'line-info' (default):
89+
// Shows a bar that tells you how many lines are collapsed. If you are
90+
// using the oldFile/newFile API then you can click those bars to
91+
// expand the content between them
92+
//
93+
// 'metadata':
94+
// Shows the content you'd see in a normal patch file, usually in some
95+
// format like '@@ -60,6 +60,22 @@'. You cannot use these to expand
96+
// hidden content
97+
//
98+
// 'simple':
99+
// Just a subtle bar separator between each hunk
100+
hunkSeparators: "line-info",
101+
// On lines that have both additions and deletions, we can run a
102+
// separate diff check to mark parts of the lines that change.
103+
// 'none':
104+
// Do not show these secondary highlights
105+
//
106+
// 'char':
107+
// Show changes at a per character granularity
108+
//
109+
// 'word':
110+
// Show changes but rounded up to word boundaries
111+
//
112+
// 'word-alt' (default):
113+
// Similar to 'word', however we attempt to minimize single character
114+
// gaps between highlighted changes
115+
lineDiffType: "word-alt",
116+
// If lines exceed these character lengths then we won't perform the
117+
// line lineDiffType check
118+
maxLineDiffLength: 1000,
119+
// If any line in the diff exceeds this value then we won't attempt to
120+
// syntax highlight the diff
121+
maxLineLengthForHighlighting: 1000,
122+
// Enabling this property will hide the file header with file name and
123+
// diff stats.
124+
disableFileHeader: true,
125+
// You can optionally pass a render function for rendering out line
126+
// annotations. Just return the dom node to render
127+
// renderAnnotation(annotation: DiffLineAnnotation<T>): HTMLElement {
128+
// // Despite the diff itself being rendered in the shadow dom,
129+
// // annotations are inserted via the web components 'slots' api and you
130+
// // can use all your normal normal css and styling for them
131+
// const element = document.createElement("div")
132+
// element.innerText = annotation.metadata.threadId
133+
// return element
134+
// },
135+
...others,
136+
})
137+
138+
instance.render({
139+
oldFile: local.before,
140+
newFile: local.after,
141+
lineAnnotations: local.annotations,
142+
containerWrapper: container,
143+
})
144+
})
145+
146+
return (
147+
<div
148+
style={{
149+
"--pjs-font-family": "var(--font-family-mono)",
150+
"--pjs-font-size": "var(--font-size-small)",
151+
"--pjs-line-height": "24px",
152+
"--pjs-tab-size": 4,
153+
"--pjs-font-features": "var(--font-family-mono--font-feature-settings)",
154+
"--pjs-header-font-family": "var(--font-family-sans)",
155+
}}
156+
ref={container}
157+
/>
158+
)
159+
}

0 commit comments

Comments
 (0)