summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-06-05 23:42:04 -0400
committerDax Raad <[email protected]>2025-06-05 23:42:04 -0400
commit265f427d2a11542e5e2df7fb50534608a32260bd (patch)
tree44da2aaac42fc03faf60108df81c8bfb953b7dbd
parent16520261f460e44fa85b3b6f82f462a79e074a18 (diff)
downloadopencode-265f427d2a11542e5e2df7fb50534608a32260bd.tar.gz
opencode-265f427d2a11542e5e2df7fb50534608a32260bd.zip
lsp progress
-rw-r--r--packages/opencode/src/app/app.ts10
-rw-r--r--packages/opencode/src/auth/anthropic.ts1
-rw-r--r--packages/opencode/src/cli/cmd/cmd.ts5
-rw-r--r--packages/opencode/src/cli/cmd/run.ts8
-rw-r--r--packages/opencode/src/cli/cmd/scrap.ts21
-rw-r--r--packages/opencode/src/cli/version.ts6
-rw-r--r--packages/opencode/src/config/config.ts1
-rw-r--r--packages/opencode/src/index.ts13
-rw-r--r--packages/opencode/src/lsp/client.ts123
-rw-r--r--packages/opencode/src/lsp/index.ts9
-rw-r--r--packages/tui/go.mod13
-rw-r--r--packages/tui/go.sum20
-rw-r--r--packages/tui/gopls.log44
13 files changed, 169 insertions, 105 deletions
diff --git a/packages/opencode/src/app/app.ts b/packages/opencode/src/app/app.ts
index 88f115267..5bded58a6 100644
--- a/packages/opencode/src/app/app.ts
+++ b/packages/opencode/src/app/app.ts
@@ -32,7 +32,11 @@ export namespace App {
const APP_JSON = "app.json"
- async function create(input: { cwd: string; version: string }) {
+ async function create(input: {
+ cwd: string
+ version: string
+ printLogs?: boolean
+ }) {
const git = await Filesystem.findUp(".git", input.cwd).then((x) =>
x ? path.dirname(x) : undefined,
)
@@ -58,7 +62,7 @@ export namespace App {
}
>()
- await Log.file(path.join(data, "log"))
+ if (!input.printLogs) await Log.file(path.join(data, "log"))
const info: Info = {
user: os.userInfo().username,
@@ -106,7 +110,7 @@ export namespace App {
}
export async function provide<T extends (app: Info) => any>(
- input: { cwd: string; version: string },
+ input: { cwd: string; version: string; printLogs?: boolean },
cb: T,
) {
const app = await create(input)
diff --git a/packages/opencode/src/auth/anthropic.ts b/packages/opencode/src/auth/anthropic.ts
index 5d12f507b..f35d39ad4 100644
--- a/packages/opencode/src/auth/anthropic.ts
+++ b/packages/opencode/src/auth/anthropic.ts
@@ -53,7 +53,6 @@ export namespace AuthAnthropic {
if (!(await file.exists())) return
const result = await file.json()
const refresh = result.refresh_token
- const now = Date.now()
const response = await fetch(
"https://console.anthropic.com/v1/oauth/token",
{
diff --git a/packages/opencode/src/cli/cmd/cmd.ts b/packages/opencode/src/cli/cmd/cmd.ts
new file mode 100644
index 000000000..ee6da7b45
--- /dev/null
+++ b/packages/opencode/src/cli/cmd/cmd.ts
@@ -0,0 +1,5 @@
+import type { CommandModule } from "yargs"
+
+export function cmd<T, U>(input: CommandModule<T, U>) {
+ return input
+}
diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts
index e5ce3784b..7016c250d 100644
--- a/packages/opencode/src/cli/cmd/run.ts
+++ b/packages/opencode/src/cli/cmd/run.ts
@@ -1,12 +1,12 @@
import type { Argv } from "yargs"
import { App } from "../../app/app"
-import { version } from "bun"
import { Bus } from "../../bus"
import { Provider } from "../../provider/provider"
import { Session } from "../../session"
import { Share } from "../../share/share"
import { Message } from "../../session/message"
import { UI } from "../ui"
+import { VERSION } from "../version"
export const RunCommand = {
command: "run [message..]",
@@ -26,15 +26,13 @@ export const RunCommand = {
},
handler: async (args: { message: string[]; session?: string }) => {
const message = args.message.join(" ")
- await App.provide({ cwd: process.cwd(), version }, async () => {
+ await App.provide({ cwd: process.cwd(), version: "0.0.0" }, async () => {
await Share.init()
const session = args.session
? await Session.get(args.session)
: await Session.create()
-
-
- UI.print(UI.Style.TEXT_HIGHLIGHT_BOLD + "◍ OpenCode", version)
+ UI.print(UI.Style.TEXT_HIGHLIGHT_BOLD + "◍ OpenCode", VERSION)
UI.empty()
UI.print(UI.Style.TEXT_NORMAL_BOLD + "> ", message)
UI.empty()
diff --git a/packages/opencode/src/cli/cmd/scrap.ts b/packages/opencode/src/cli/cmd/scrap.ts
new file mode 100644
index 000000000..13cd96ad2
--- /dev/null
+++ b/packages/opencode/src/cli/cmd/scrap.ts
@@ -0,0 +1,21 @@
+import { App } from "../../app/app"
+import { VERSION } from "../version"
+import { LSP } from "../../lsp"
+import { cmd } from "./cmd"
+
+export const ScrapCommand = cmd({
+ command: "scrap <file>",
+ builder: (yargs) =>
+ yargs.positional("file", { type: "string", demandOption: true }),
+ describe: "test command",
+ async handler(args) {
+ await App.provide(
+ { cwd: process.cwd(), version: VERSION, printLogs: true },
+ async () => {
+ await LSP.file(args.file)
+ const diagnostics = await LSP.diagnostics()
+ console.log(diagnostics)
+ },
+ )
+ },
+})
diff --git a/packages/opencode/src/cli/version.ts b/packages/opencode/src/cli/version.ts
new file mode 100644
index 000000000..43dc9745d
--- /dev/null
+++ b/packages/opencode/src/cli/version.ts
@@ -0,0 +1,6 @@
+declare global {
+ const OPENCODE_VERSION: string
+}
+
+export const VERSION =
+ typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "dev"
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 8beb78e9f..33d565eec 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -1,7 +1,6 @@
import { Log } from "../util/log"
import { z } from "zod"
import { App } from "../app/app"
-import { Provider } from "../provider/provider"
import { Filesystem } from "../util/filesystem"
export namespace Config {
diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts
index ef2daa95c..e7b6369a1 100644
--- a/packages/opencode/src/index.ts
+++ b/packages/opencode/src/index.ts
@@ -13,21 +13,17 @@ import { hideBin } from "yargs/helpers"
import { RunCommand } from "./cli/cmd/run"
import { LoginAnthropicCommand } from "./cli/cmd/login-anthropic"
import { GenerateCommand } from "./cli/cmd/generate"
-
-declare global {
- const OPENCODE_VERSION: string
-}
-
-const version = typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "dev"
+import { VERSION } from "./cli/version"
+import { ScrapCommand } from "./cli/cmd/scrap"
yargs(hideBin(process.argv))
.scriptName("opencode")
- .version(version)
+ .version(VERSION)
.command({
command: "$0",
describe: "Start OpenCode TUI",
handler: async () => {
- await App.provide({ cwd: process.cwd(), version }, async () => {
+ await App.provide({ cwd: process.cwd(), version: VERSION }, async () => {
await Share.init()
const server = Server.listen()
@@ -66,6 +62,7 @@ yargs(hideBin(process.argv))
})
.command(RunCommand)
.command(GenerateCommand)
+ .command(ScrapCommand)
.command({
command: "login",
describe: "generate credentials for various providers",
diff --git a/packages/opencode/src/lsp/client.ts b/packages/opencode/src/lsp/client.ts
index 52dbc22a1..1722db84c 100644
--- a/packages/opencode/src/lsp/client.ts
+++ b/packages/opencode/src/lsp/client.ts
@@ -1,4 +1,4 @@
-import { spawn } from "child_process"
+import { Readable, Writable } from "stream"
import path from "path"
import {
createMessageConnection,
@@ -29,19 +29,60 @@ export namespace LSPClient {
),
}
- export async function create(input: { cmd: string[]; serverID: string }) {
- log.info("starting client", input)
-
+ export async function create(input: {
+ cmd: string[]
+ serverID: string
+ initialization?: any
+ }) {
const app = App.info()
- const [command, ...args] = input.cmd
- const server = spawn(command, args, {
- stdio: ["pipe", "pipe", "pipe"],
+ log.info("starting client", {
+ ...input,
+ cwd: app.path.cwd,
+ })
+
+ const server = Bun.spawn({
+ cmd: input.cmd,
+ stdin: "pipe",
+ stdout: "pipe",
+ stderr: "pipe",
cwd: app.path.cwd,
})
+ const stdout = new Readable({
+ read() {},
+ construct(callback) {
+ const reader = server.stdout.getReader()
+ const pump = async () => {
+ try {
+ while (true) {
+ const { done, value } = await reader.read()
+ if (done) {
+ this.push(null)
+ break
+ }
+ this.push(Buffer.from(value))
+ }
+ } catch (error) {
+ this.destroy(
+ error instanceof Error ? error : new Error(String(error)),
+ )
+ }
+ }
+ pump()
+ callback()
+ },
+ })
+
+ const stdin = new Writable({
+ write(chunk, _encoding, callback) {
+ server.stdin.write(chunk)
+ callback()
+ },
+ })
+
const connection = createMessageConnection(
- new StreamMessageReader(server.stdout),
- new StreamMessageWriter(server.stdin),
+ new StreamMessageReader(stdout),
+ new StreamMessageWriter(stdin),
)
const diagnostics = new Map<string, Diagnostic[]>()
@@ -50,71 +91,37 @@ export namespace LSPClient {
log.info("textDocument/publishDiagnostics", {
path,
})
- const exists = diagnostics.has(path)
diagnostics.set(path, params.diagnostics)
- // servers seem to send one blank publishDiagnostics event before the first real one
- if (!exists && !params.diagnostics.length) return
Bus.publish(Event.Diagnostics, { path, serverID: input.serverID })
})
+ connection.onRequest("workspace/configuration", async () => {
+ return [{}]
+ })
connection.listen()
- await connection.sendRequest("initialize", {
+ const response = await connection.sendRequest("initialize", {
processId: server.pid,
- initializationOptions: {
- workspaceFolders: [
- {
- name: "workspace",
- uri: "file://" + app.path.cwd,
- },
- ],
- tsserver: {
- path: require.resolve("typescript/lib/tsserver.js"),
+ workspaceFolders: [
+ {
+ name: "workspace",
+ uri: "file://" + app.path.cwd,
},
+ ],
+ initializationOptions: {
+ ...input.initialization,
},
capabilities: {
workspace: {
configuration: true,
- didChangeConfiguration: {
- dynamicRegistration: true,
- },
- didChangeWatchedFiles: {
- dynamicRegistration: true,
- relativePatternSupport: true,
- },
},
textDocument: {
synchronization: {
- dynamicRegistration: true,
- didSave: true,
- },
- completion: {
- completionItem: {},
- },
- codeLens: {
- dynamicRegistration: true,
- },
- documentSymbol: {},
- codeAction: {
- codeActionLiteralSupport: {
- codeActionKind: {
- valueSet: [],
- },
- },
+ didOpen: true,
},
publishDiagnostics: {
versionSupport: true,
},
- semanticTokens: {
- requests: {
- range: {},
- full: {},
- },
- tokenTypes: [],
- tokenModifiers: [],
- formats: [],
- },
},
- window: {},
},
})
await connection.sendNotification("initialized", {})
@@ -131,6 +138,9 @@ export namespace LSPClient {
},
notify: {
async open(input: { path: string }) {
+ input.path = path.isAbsolute(input.path)
+ ? input.path
+ : path.resolve(app.path.cwd, input.path)
const file = Bun.file(input.path)
const text = await file.text()
const opened = files.has(input.path)
@@ -170,6 +180,9 @@ export namespace LSPClient {
return diagnostics
},
async waitForDiagnostics(input: { path: string }) {
+ input.path = path.isAbsolute(input.path)
+ ? input.path
+ : path.resolve(app.path.cwd, input.path)
log.info("waiting for diagnostics", input)
let unsub: () => void
let timeout: NodeJS.Timeout
diff --git a/packages/opencode/src/lsp/index.ts b/packages/opencode/src/lsp/index.ts
index 90463e079..72cc7363a 100644
--- a/packages/opencode/src/lsp/index.ts
+++ b/packages/opencode/src/lsp/index.ts
@@ -36,6 +36,7 @@ export namespace LSP {
const client = await LSPClient.create({
cmd: match.command,
serverID: match.id,
+ initialization: match.initialization,
})
s.clients.set(match.id, client)
}
@@ -87,6 +88,7 @@ export namespace LSP {
const AUTO: {
id: string
command: string[]
+ initialization?: any
extensions: string[]
install?: () => Promise<void>
}[] = [
@@ -105,10 +107,15 @@ export namespace LSP {
".mtsx",
".ctsx",
],
+ initialization: {
+ tsserver: {
+ path: require.resolve("typescript/lib/tsserver.js"),
+ },
+ },
},
{
id: "golang",
- command: ["gopls"],
+ command: ["gopls" /*"-logfile", "gopls.log", "-rpc.trace", "-vv"*/],
extensions: [".go"],
},
]
diff --git a/packages/tui/go.mod b/packages/tui/go.mod
index a0fbe832f..76d2d7bd5 100644
--- a/packages/tui/go.mod
+++ b/packages/tui/go.mod
@@ -3,6 +3,7 @@ module github.com/sst/opencode
go 1.24.0
require (
+ github.com/BurntSushi/toml v1.5.0
github.com/alecthomas/chroma/v2 v2.15.0
github.com/bmatcuk/doublestar/v4 v4.8.1
github.com/catppuccin/go v0.3.0
@@ -25,7 +26,6 @@ require golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
require (
dario.cat/mergo v1.0.2 // indirect
- github.com/BurntSushi/toml v1.5.0 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/atombender/go-jsonschema v0.20.0 // indirect
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect
@@ -46,6 +46,7 @@ require (
github.com/sanity-io/litter v1.5.8 // indirect
github.com/sosodev/duration v1.3.1 // indirect
github.com/speakeasy-api/openapi-overlay v0.9.0 // indirect
+ github.com/spf13/cobra v1.9.1 // indirect
github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/tools v0.31.0 // indirect
@@ -59,11 +60,9 @@ require (
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
- github.com/davecgh/go-spew v1.1.1 // indirect
github.com/disintegration/imaging v1.6.2
github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
- github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -73,20 +72,12 @@ require (
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
- github.com/pelletier/go-toml/v2 v2.2.3 // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
- github.com/sagikazarmark/locafero v0.7.0 // indirect
- github.com/sourcegraph/conc v0.3.0 // indirect
- github.com/spf13/afero v1.12.0 // indirect
- github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
- github.com/subosito/gotenv v1.6.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/yuin/goldmark v1.7.8 // indirect
github.com/yuin/goldmark-emoji v1.0.5 // indirect
- go.uber.org/multierr v1.11.0 // indirect
golang.org/x/image v0.26.0
golang.org/x/net v0.39.0 // indirect
golang.org/x/sync v0.13.0 // indirect
diff --git a/packages/tui/go.sum b/packages/tui/go.sum
index 488f30793..03689fe8c 100644
--- a/packages/tui/go.sum
+++ b/packages/tui/go.sum
@@ -63,8 +63,6 @@ github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aT
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
-github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
-github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
@@ -78,8 +76,6 @@ github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
-github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
-github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY=
github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -169,8 +165,6 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
-github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
-github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -185,8 +179,6 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
-github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/sanity-io/litter v1.5.8 h1:uM/2lKrWdGbRXDrIq08Lh9XtVYoeGtcQxk9rtQ7+rYg=
github.com/sanity-io/litter v1.5.8/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@@ -194,20 +186,12 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4=
github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg=
-github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
-github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/speakeasy-api/openapi-overlay v0.9.0 h1:Wrz6NO02cNlLzx1fB093lBlYxSI54VRhy1aSutx0PQg=
github.com/speakeasy-api/openapi-overlay v0.9.0/go.mod h1:f5FloQrHA7MsxYg9djzMD5h6dxrHjVVByWKh7an8TRc=
-github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
-github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
-github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
-github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY=
-github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -216,8 +200,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
-github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk=
@@ -231,8 +213,6 @@ github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk=
github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
-go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
-go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
diff --git a/packages/tui/gopls.log b/packages/tui/gopls.log
new file mode 100644
index 000000000..a515730d7
--- /dev/null
+++ b/packages/tui/gopls.log
@@ -0,0 +1,44 @@
+[Trace - 22:23:41.516 PM] Sending request 'initialize - (0)'.
+Params: {"processId":1561573,"workspaceFolders":[{"name":"workspace","uri":"file:///home/thdxr/dev/projects/sst/opencode/packages/tui"}],"initializationOptions":{},"capabilities":{"workspace":{"configuration":true},"textDocument":{"synchronization":{"didOpen":true},"publishDiagnostics":{"versionSupport":true}}}}
+
+
+[Trace - 22:23:41.517 PM] Received response 'initialize - (0)' in 0ms.
+Result: {"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"save":{}},"completionProvider":{"triggerCharacters":["."]},"hoverProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"codeActionProvider":true,"codeLensProvider":{},"documentLinkProvider":{},"workspaceSymbolProvider":true,"documentFormattingProvider":true,"renameProvider":true,"foldingRangeProvider":true,"selectionRangeProvider":true,"executeCommandProvider":{"commands":["gopls.add_dependency","gopls.add_import","gopls.add_telemetry_counters","gopls.add_test","gopls.apply_fix","gopls.assembly","gopls.change_signature","gopls.check_upgrades","gopls.client_open_url","gopls.diagnose_files","gopls.doc","gopls.edit_go_directive","gopls.extract_to_new_file","gopls.fetch_vulncheck_result","gopls.free_symbols","gopls.gc_details","gopls.generate","gopls.go_get_package","gopls.list_imports","gopls.list_known_packages","gopls.maybe_prompt_for_telemetry","gopls.mem_stats","gopls.modules","gopls.package_symbols","gopls.packages","gopls.regenerate_cgo","gopls.remove_dependency","gopls.reset_go_mod_diagnostics","gopls.run_go_work_command","gopls.run_govulncheck","gopls.run_tests","gopls.scan_imports","gopls.start_debugging","gopls.start_profile","gopls.stop_profile","gopls.tidy","gopls.update_go_sum","gopls.upgrade_dependency","gopls.vendor","gopls.views","gopls.vulncheck","gopls.workspace_stats"]},"callHierarchyProvider":true,"semanticTokensProvider":{"legend":{"tokenTypes":["namespace","type","typeParameter","parameter","variable","function","method","macro","keyword","comment","string","number","operator","label"],"tokenModifiers":["definition","readonly","defaultLibrary","array","bool","chan","format","interface","map","number","pointer","signature","slice","string","struct"]},"range":true,"full":true},"inlayHintProvider":{},"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":"workspace/didChangeWorkspaceFolders"}}},"serverInfo":{"name":"gopls","version":"{\"GoVersion\":\"go1.24.2\",\"Path\":\"golang.org/x/tools/gopls\",\"Main\":{\"Path\":\"golang.org/x/tools/gopls\",\"Version\":\"(devel)\",\"Sum\":\"\",\"Replace\":null},\"Deps\":[{\"Path\":\"github.com/BurntSushi/toml\",\"Version\":\"v1.4.1-0.20240526193622-a339e1f7089c\",\"Sum\":\"h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=\",\"Replace\":null},{\"Path\":\"github.com/google/go-cmp\",\"Version\":\"v0.6.0\",\"Sum\":\"h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=\",\"Replace\":null},{\"Path\":\"golang.org/x/exp/typeparams\",\"Version\":\"v0.0.0-20241210194714-1829a127f884\",\"Sum\":\"h1:1xaZTydL5Gsg78QharTwKfA9FY9CZ1VQj6D/AZEvHR0=\",\"Replace\":null},{\"Path\":\"golang.org/x/mod\",\"Version\":\"v0.23.0\",\"Sum\":\"h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=\",\"Replace\":null},{\"Path\":\"golang.org/x/sync\",\"Version\":\"v0.11.0\",\"Sum\":\"h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=\",\"Replace\":null},{\"Path\":\"golang.org/x/telemetry\",\"Version\":\"v0.0.0-20241220003058-cc96b6e0d3d9\",\"Sum\":\"h1:L2k9GUV2TpQKVRGMjN94qfUMgUwOFimSQ6gipyJIjKw=\",\"Replace\":null},{\"Path\":\"golang.org/x/text\",\"Version\":\"v0.22.0\",\"Sum\":\"h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=\",\"Replace\":null},{\"Path\":\"golang.org/x/tools\",\"Version\":\"v0.30.1-0.20250221230316-5055f70f240c\",\"Sum\":\"h1:Ja/5gV5a9Vvho3p2NC/T2TtxhHjrWS/2DvCKMvA0a+Y=\",\"Replace\":null},{\"Path\":\"golang.org/x/vuln\",\"Version\":\"v1.1.3\",\"Sum\":\"h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw=\",\"Replace\":null},{\"Path\":\"honnef.co/go/tools\",\"Version\":\"v0.5.1\",\"Sum\":\"h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=\",\"Replace\":null},{\"Path\":\"mvdan.cc/gofumpt\",\"Version\":\"v0.7.0\",\"Sum\":\"h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=\",\"Replace\":null},{\"Path\":\"mvdan.cc/xurls/v2\",\"Version\":\"v2.5.0\",\"Sum\":\"h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=\",\"Replace\":null}],\"Settings\":[{\"Key\":\"-buildmode\",\"Value\":\"pie\"},{\"Key\":\"-compiler\",\"Value\":\"gc\"},{\"Key\":\"-ldflags\",\"Value\":\"-compressdwarf=false -linkmode external -extldflags \\\"-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,-z,pack-relative-relocs\\\"\"},{\"Key\":\"DefaultGODEBUG\",\"Value\":\"gotestjsonbuildtext=1,multipathtcp=0,randseednop=0,rsa1024min=0,tlsmlkem=0,x509rsacrt=0,x509usepolicies=0\"},{\"Key\":\"CGO_ENABLED\",\"Value\":\"1\"},{\"Key\":\"CGO_CFLAGS\",\"Value\":\"-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security -fstack-clash-protection -fcf-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -g -ffile-prefix-map=/build/gopls/src=/usr/src/debug/gopls\"},{\"Key\":\"CGO_CPPFLAGS\",\"Value\":\"\"},{\"Key\":\"CGO_CXXFLAGS\",\"Value\":\"-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security -fstack-clash-protection -fcf-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -Wp,-D_GLIBCXX_ASSERTIONS -g -ffile-prefix-map=/build/gopls/src=/usr/src/debug/gopls\"},{\"Key\":\"CGO_LDFLAGS\",\"Value\":\"\"},{\"Key\":\"GOARCH\",\"Value\":\"amd64\"},{\"Key\":\"GOOS\",\"Value\":\"linux\"},{\"Key\":\"GOAMD64\",\"Value\":\"v1\"}],\"Version\":\"(devel)\"}"}}
+
+
+[Trace - 22:23:41.519 PM] Sending notification 'initialized'.
+Params: {}
+
+
+[Trace - 22:23:41.519 PM] Received notification 'window/showMessage'.
+Params: {"type":4,"message":"Loading packages..."}
+
+
+[Trace - 22:23:41.519 PM] Received request 'workspace/configuration - (1)'.
+Params: {"items":[{"scopeUri":"file:///home/thdxr/dev/projects/sst/opencode/packages/tui","section":"gopls"}]}
+
+
+[Trace - 22:23:41.519 PM] Sending notification 'textDocument/didOpen'.
+Params: {"textDocument":{"uri":"file:///home/thdxr/dev/projects/sst/opencode/packages/tui/foo.go","languageId":"go","version":1749176621519,"text":"package main\n\nvar foo = \"bar\"\n\nfunc main() {\n\tvar number int\n\tnumber = \"123\"\n}\n"}}
+
+
+[Trace - 22:23:41.520 PM] Sending response 'workspace/configuration - (1)' in 0ms.
+Result: [{}]
+
+
+[Trace - 22:23:41.526 PM] Received notification 'window/logMessage'.
+Params: {"type":3,"message":"2025/06/05 22:23:41 Created View (#1)\n\tdirectory=/home/thdxr/dev/projects/sst/opencode/packages/tui\n\tview_type=\"GoMod\"\n\troot_dir=\"file:///home/thdxr/dev/projects/sst/opencode/packages/tui\"\n\tgo_version=\"go version go1.24.3 linux/amd64\"\n\tbuild_flags=[]\n\tenv={GOOS:linux GOARCH:amd64 GOCACHE:/home/thdxr/.cache/go-build GOMODCACHE:/home/thdxr/dev/gopath/pkg/mod GOPATH:/home/thdxr/dev/gopath GOPRIVATE: GOFLAGS: GO111MODULE: GOTOOLCHAIN:auto GOROOT:/usr/lib/go GoVersion:24 GoVersionOutput:go version go1.24.3 linux/amd64\n ExplicitGOWORK: EffectiveGOPACKAGESDRIVER:}\n\tenv_overlay=[]\n"}
+
+
+[Trace - 22:23:41.676 PM] Received notification 'window/logMessage'.
+Params: {"type":3,"message":"2025/06/05 22:23:41 go/packages.Load #1\n\tview_id=\"1\"\n\tsnapshot=0\n\tdirectory=/home/thdxr/dev/projects/sst/opencode/packages/tui\n\tquery=[/home/thdxr/dev/projects/sst/opencode/packages/tui/... builtin]\n\tpackages=31\n\tduration=150.178807ms\n"}
+
+
+[Trace - 22:23:41.689 PM] Received notification 'window/showMessage'.
+Params: {"type":3,"message":"Finished loading packages."}
+
+
+[Trace - 22:23:41.754 PM] Received notification 'textDocument/publishDiagnostics'.
+Params: {"uri":"file:///home/thdxr/dev/projects/sst/opencode/packages/tui/foo.go","diagnostics":[{"range":{"start":{"line":5,"character":5},"end":{"line":5,"character":11}},"severity":1,"code":"UnusedVar","codeDescription":{"href":"https://pkg.go.dev/golang.org/x/tools/internal/typesinternal#UnusedVar"},"source":"compiler","message":"declared and not used: number","tags":[1]},{"range":{"start":{"line":6,"character":10},"end":{"line":6,"character":15}},"severity":1,"code":"IncompatibleAssign","codeDescription":{"href":"https://pkg.go.dev/golang.org/x/tools/internal/typesinternal#IncompatibleAssign"},"source":"compiler","message":"cannot use \"123\" (untyped string constant) as int value in assignment"}]}
+
+