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
24 changes: 12 additions & 12 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@
"@openauthjs/openauth": "catalog:",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/sdk": "workspace:*",
"@opentui/core": "0.0.0-20251001-886e38c1",
"@opentui/solid": "0.0.0-20251001-886e38c1",
"@opentui/core": "0.0.0-20251001-d57654da",
"@opentui/solid": "0.0.0-20251001-d57654da",
"@standard-schema/spec": "1.0.0",
"@zip.js/zip.js": "2.7.62",
"ai": "catalog:",
Expand All @@ -183,7 +183,7 @@
"turndown": "7.2.0",
"ulid": "catalog:",
"vscode-jsonrpc": "8.2.1",
"web-tree-sitter": "0.22.6",
"web-tree-sitter": "0.26.0",
"xdg-basedir": "5.1.0",
"yargs": "18.0.0",
"zod": "catalog:",
Expand Down Expand Up @@ -835,21 +835,21 @@

"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],

"@opentui/core": ["@opentui/core@0.0.0-20251001-886e38c1", "", { "dependencies": { "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.0.0-20251001-886e38c1", "@opentui/core-darwin-x64": "0.0.0-20251001-886e38c1", "@opentui/core-linux-arm64": "0.0.0-20251001-886e38c1", "@opentui/core-linux-x64": "0.0.0-20251001-886e38c1", "@opentui/core-win32-arm64": "0.0.0-20251001-886e38c1", "@opentui/core-win32-x64": "0.0.0-20251001-886e38c1", "bun-webgpu": "0.1.3", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": ">=0.25.0" } }, "sha512-mbElYuirjjWynIpc4pkNTtIYxK9zmEmEjgaV5Z1wyrSy/e5Ld5nKs39wBLKPFzx/u9XcIIz31YRLNW3hHXlxEQ=="],
"@opentui/core": ["@opentui/core@0.0.0-20251001-d57654da", "", { "dependencies": { "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.0.0-20251001-d57654da", "@opentui/core-darwin-x64": "0.0.0-20251001-d57654da", "@opentui/core-linux-arm64": "0.0.0-20251001-d57654da", "@opentui/core-linux-x64": "0.0.0-20251001-d57654da", "@opentui/core-win32-arm64": "0.0.0-20251001-d57654da", "@opentui/core-win32-x64": "0.0.0-20251001-d57654da", "bun-webgpu": "0.1.3", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": ">=0.26.0" } }, "sha512-xDERJfK0+xn3atLPPyjliCPTZOGMZ3Is5NOKuCMZnpICm3zNirJMa02/8FGmxz0fbPL+ll1MTO1qdpl2DZBb6g=="],

"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.0.0-20251001-886e38c1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b5+wxaIaEnT0qdCxeOXgW5q0DP/y1r1dTVEVwT0JUK/NXkTa+MPIkHfPg8Ns82v/Bpv2pdvgZkcgBb8f8F0Zvg=="],
"@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.0.0-20251001-d57654da", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1Q2F9VYRQO/nZioOQmbJf3gpouBUDYE8fC5oeiw9p0fnOmcxPSN0LiS7YJbQcD+x5cK5N5Sv7jxe9ar44Wjivg=="],

"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.0.0-20251001-886e38c1", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ct2HbxYp9RTXbESilA+ypLG/1mZXn8fAnMUzrxJ77T10yEIzQx5AQPkMJkIwx1hMDmVVgK5M+Eryuk9/IWagAQ=="],
"@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.0.0-20251001-d57654da", "", { "os": "darwin", "cpu": "x64" }, "sha512-d1iXRP2QdQe2k4Dwwq9QGDay1b2//YIua7N8DOjWztVHDGDKO/doBWfM6f4+HYEEiXegmZX+1hX/VXYEEKTxWA=="],

"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.0.0-20251001-886e38c1", "", { "os": "linux", "cpu": "arm64" }, "sha512-DVimZeRZNmMXdLmziiKGlT04J9NBk1VhkjUcWNz1xKNJz3e0VAJHGE9+B4aUCT7iT06bj6bnmfZuZDlCtmLEyg=="],
"@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.0.0-20251001-d57654da", "", { "os": "linux", "cpu": "arm64" }, "sha512-dc2C1yZlE5o0NfNzV7rqYCqqRBp5TRIGje3u2QEY2xDY4qlti4dS8cSOrLTWrYWrIoCmuN7W+eGrOH4NuUF+fw=="],

"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.0.0-20251001-886e38c1", "", { "os": "linux", "cpu": "x64" }, "sha512-obw90FMU9FXnSgL+4DYBaiEPW6PNz7TIFu7Vc39yXRFfLU9eM6Jrj+KRgmEzbsLAqWB246rmAAHnAX8y0T3qpQ=="],
"@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.0.0-20251001-d57654da", "", { "os": "linux", "cpu": "x64" }, "sha512-sjzj1Jos7VRIl0I7JjZcOu7T4jmMdJgoRTV+U1q9wBMSVQpV9Prb50N/egGeX8D0bEF0V1T6bWkph9xgCMNKsg=="],

"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.0.0-20251001-886e38c1", "", { "os": "win32", "cpu": "arm64" }, "sha512-me60jLhjwmGrKS18ny0quBk3eatCR5uKTTzkxnqxgqdHXaM/tbC2S9SoIOkOLWwySLjj69n8xLzuZrZSOojssQ=="],
"@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.0.0-20251001-d57654da", "", { "os": "win32", "cpu": "arm64" }, "sha512-F3ySKR284VLS1UUDAtcya7RJRuknghlANwlrYxiJkVOjOa7swAaxGZNYdMXmRRvOmMraeOgHWHVK3y0qdPFV9A=="],

"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.0.0-20251001-886e38c1", "", { "os": "win32", "cpu": "x64" }, "sha512-WeoojsODqLH5nX9P9UF7QjFAKDq9Z0SLBDzvcRo7NyU3Wd9PhcQf1v9Cjc42lYgF/EOX24UGv2pDLqT0mhIANA=="],
"@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.0.0-20251001-d57654da", "", { "os": "win32", "cpu": "x64" }, "sha512-aVpSsEqke8ryVh2oChQrwcz4+zYPh77radM+lks5A2bo926r3dcFWNuIBFHwGTJ0tll5iAXw2MdfHo+2r8srxQ=="],

"@opentui/solid": ["@opentui/solid@0.0.0-20251001-886e38c1", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.0.0-20251001-886e38c1", "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-mEydaU1JrFL7sSz0lAVIS80IprmhTpqUFabOyLJSReSQ3SSA3tLssdJCWNdqbLXAMaP5NgpmQu6iOwvVxZdJFA=="],
"@opentui/solid": ["@opentui/solid@0.0.0-20251001-d57654da", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.0.0-20251001-d57654da", "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-8rJDFe8b2icFs7kTNT4ypDCIKU0RTgE2bION197RtYh9Mu6ViIagqrfGZloRdIRLcRYroYqXdl21IVh5ji2BsQ=="],

"@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="],

Expand Down Expand Up @@ -3107,7 +3107,7 @@

"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],

"web-tree-sitter": ["web-tree-sitter@0.22.6", "", {}, "sha512-hS87TH71Zd6mGAmYCvlgxeGDjqd9GTeqXNqTT+u0Gs51uIozNIaaq/kUAbV/Zf56jb2ZOyG8BxZs2GG9wbLi6Q=="],
"web-tree-sitter": ["web-tree-sitter@0.26.0", "", {}, "sha512-wGGAMnJEMF8wy33iEGxSvnyEOfVLzSaa3x6g66aEHsL/hsgFb6IVPrpacIordAMz198pE9qReCEqFUuM0pnfwg=="],

"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],

Expand Down
6 changes: 3 additions & 3 deletions packages/opencode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
"@openauthjs/openauth": "catalog:",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/sdk": "workspace:*",
"@opentui/core": "0.0.0-20251001-886e38c1",
"@opentui/solid": "0.0.0-20251001-886e38c1",
"@opentui/core": "0.0.0-20251001-d57654da",
"@opentui/solid": "0.0.0-20251001-d57654da",
"@standard-schema/spec": "1.0.0",
"@zip.js/zip.js": "2.7.62",
"ai": "catalog:",
Expand All @@ -65,7 +65,7 @@
"turndown": "7.2.0",
"ulid": "catalog:",
"vscode-jsonrpc": "8.2.1",
"web-tree-sitter": "0.22.6",
"web-tree-sitter": "0.26.0",
"xdg-basedir": "5.1.0",
"yargs": "18.0.0",
"zod": "catalog:"
Expand Down
5 changes: 4 additions & 1 deletion packages/opencode/script/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ for (const [os, arch] of targets) {
await $`mkdir -p ../../node_modules/${opentui}`
await $`npm pack npm pack ${opentui}`.cwd(path.join(dir, "../../node_modules")).quiet()
await $`tar -xf ../../node_modules/${opentui.replace("@opentui/", "opentui-")}-*.tgz -C ../../node_modules/${opentui} --strip-components=1`

await Bun.build({
conditions: ["browser"],
tsconfig: "./tsconfig.json",
Expand All @@ -50,12 +51,14 @@ for (const [os, arch] of targets) {
execArgv: [`--user-agent=opencode/${version}`, `--env-file=""`, `--`],
windows: {},
},
entrypoints: ["./src/index.ts", "./src/cli/cmd/tui/worker.ts"],
entrypoints: ["./src/index.ts", path.resolve(dir, "../../node_modules/@opentui/core/parser.worker.js")],
define: {
OPENCODE_VERSION: `'${version}'`,
OPENCODE_TUI_PATH: `'../../../dist/${name}/bin/tui'`,
OTUI_TREE_SITTER_WORKER_PATH: "/$bunfs/root/../../node_modules/@opentui/core/parser.worker.js",
},
})

await $`rm -rf ./dist/${name}/bin/tui`
await Bun.file(`dist/${name}/package.json`).write(
JSON.stringify(
Expand Down
195 changes: 185 additions & 10 deletions packages/opencode/src/cli/cmd/tui/context/theme.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { SyntaxStyle } from "@opentui/core"

const OPENCODE_THEME = {
primary: {
dark: "#fab283",
Expand Down Expand Up @@ -243,18 +245,191 @@ type Theme = {
markdownImage: string
markdownImageText: string
markdownCodeBlock: string
syntaxComment: string
syntaxKeyword: string
syntaxFunction: string
syntaxVariable: string
syntaxString: string
syntaxNumber: string
syntaxType: string
syntaxOperator: string
syntaxPunctuation: string
}

export const Theme = Object.entries(OPENCODE_THEME).reduce((acc, [key, value]) => {
acc[key as keyof Theme] = value.dark
return acc
}, {} as Theme)
}, {} as Theme)

const syntaxThemeDark = [
{
scope: ["prompt"],
style: {
foreground: "#56b6c2",
},
},
{
scope: ["comment"],
style: {
foreground: "#808080",
italic: true,
},
},
{
scope: ["comment.documentation"],
style: {
foreground: "#808080",
italic: true,
},
},
{
scope: ["string", "symbol"],
style: {
foreground: "#7fd88f",
},
},
{
scope: ["number", "boolean"],
style: {
foreground: "#f5a742",
},
},
{
scope: ["character.special"],
style: {
foreground: "#7fd88f",
},
},
{
scope: ["keyword.return", "keyword.conditional", "keyword.repeat", "keyword.coroutine"],
style: {
foreground: "#9d7cd8",
italic: true,
},
},
{
scope: ["keyword.type"],
style: {
foreground: "#e5c07b",
bold: true,
italic: true,
},
},
{
scope: ["keyword.function", "function.method"],
style: {
foreground: "#fab283",
},
},
{
scope: ["keyword"],
style: {
foreground: "#9d7cd8",
italic: true,
},
},
{
scope: ["keyword.import"],
style: {
foreground: "#9d7cd8",
},
},
{
scope: ["operator", "keyword.operator", "punctuation.delimiter"],
style: {
foreground: "#56b6c2",
},
},
{
scope: ["keyword.conditional.ternary"],
style: {
foreground: "#56b6c2",
},
},
{
scope: ["variable", "variable.parameter", "function.method.call", "function.call"],
style: {
foreground: "#e06c75",
},
},
{
scope: ["variable.member", "function", "constructor"],
style: {
foreground: "#fab283",
},
},
{
scope: ["type", "module"],
style: {
foreground: "#e5c07b",
},
},
{
scope: ["constant"],
style: {
foreground: "#e06c75",
},
},
{
scope: ["property"],
style: {
foreground: "#e06c75",
},
},
{
scope: ["class"],
style: {
foreground: "#e5c07b",
},
},
{
scope: ["parameter"],
style: {
foreground: "#eeeeee",
},
},
{
scope: ["punctuation", "punctuation.bracket"],
style: {
foreground: "#eeeeee",
},
},
{
scope: ["variable.builtin", "type.builtin", "function.builtin", "module.builtin", "constant.builtin"],
style: {
foreground: "#7fd88f",
},
},
{
scope: ["variable.super"],
style: {
foreground: "#e06c75",
},
},
{
scope: ["string.escape", "string.regexp"],
style: {
foreground: "#7fd88f",
},
},
{
scope: ["keyword.directive"],
style: {
foreground: "#9d7cd8",
italic: true,
},
},
{
scope: ["punctuation.special"],
style: {
foreground: "#56b6c2",
},
},
{
scope: ["keyword.modifier"],
style: {
foreground: "#9d7cd8",
italic: true,
},
},
{
scope: ["keyword.exception"],
style: {
foreground: "#9d7cd8",
italic: true,
},
},
]

export const syntaxTheme = SyntaxStyle.fromTheme(syntaxThemeDark)
36 changes: 14 additions & 22 deletions packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import path from "path"
import { useRouteData } from "@tui/context/route"
import { useSync } from "@tui/context/sync"
import { SplitBorder } from "@tui/component/border"
import { Theme } from "@tui/context/theme"
import { BoxRenderable, ScrollBoxRenderable } from "@opentui/core"
import { syntaxTheme, Theme } from "@tui/context/theme"
import { BoxRenderable, pathToFiletype, ScrollBoxRenderable } from "@opentui/core"
import { Prompt, type PromptRef } from "@tui/component/prompt"
import type { AssistantMessage, Part, ToolPart, UserMessage, TextPart, ReasoningPart } from "@opencode-ai/sdk"
import { useLocal } from "@tui/context/local"
Expand Down Expand Up @@ -648,22 +648,6 @@ ToolRegistry.register<typeof BashTool>({
},
})

/*
const syntax = new SyntaxStyle({
keyword: { fg: RGBA.fromHex(Theme.syntaxKeyword), bold: true },
string: { fg: RGBA.fromHex(Theme.syntaxString) },
comment: { fg: RGBA.fromHex(Theme.syntaxComment), italic: true },
number: { fg: RGBA.fromHex(Theme.syntaxNumber) },
function: { fg: RGBA.fromHex(Theme.syntaxFunction) },
type: { fg: RGBA.fromHex(Theme.syntaxType) },
operator: { fg: RGBA.fromHex(Theme.syntaxOperator) },
variable: { fg: RGBA.fromHex(Theme.syntaxVariable) },
bracket: { fg: RGBA.fromHex(Theme.syntaxPunctuation) },
punctuation: { fg: RGBA.fromHex(Theme.syntaxPunctuation) },
default: { fg: RGBA.fromHex(Theme.syntaxVariable) },
})
*/

ToolRegistry.register<typeof ReadTool>({
name: "read",
container: "inline",
Expand Down Expand Up @@ -708,7 +692,7 @@ ToolRegistry.register<typeof WriteTool>({
<For each={numbers()}>{(value) => <text style={{ fg: Theme.textMuted }}>{value}</text>}</For>
</box>
<box paddingLeft={1} flexGrow={1}>
<text>{code()}</text>
<code filetype={pathToFiletype(props.input.filePath!)} syntaxStyle={syntaxTheme} content={code()} />
</box>
</box>
</>
Expand Down Expand Up @@ -819,13 +803,21 @@ ToolRegistry.register<typeof EditTool>({
</Match>
<Match when={code()}>
<box paddingLeft={1}>
<text>{code()}</text>
<code filetype={pathToFiletype(props.input.filePath!)} syntaxStyle={syntaxTheme} content={code()} />
</box>
</Match>
<Match when={props.input.newString && props.input.oldString}>
<box paddingLeft={1}>
<text>{props.input.oldString}</text>
<text>{props.input.newString}</text>
<code
filetype={pathToFiletype(props.input.filePath!)}
syntaxStyle={syntaxTheme}
content={props.input.oldString}
/>
<code
filetype={pathToFiletype(props.input.filePath!)}
syntaxStyle={syntaxTheme}
content={props.input.newString}
/>
</box>
</Match>
</Switch>
Expand Down
Loading
Loading