What happened, and what did you expect?
What happened:
When using the OpenCode TUI with the orchestrator agent, the LSP sidebar continues to display "LSPs will activate as files are read" even after the orchestrator has read and edited multiple files in the project.
Expected behavior:
The LSP sidebar should update to show the connected LSP servers once files are read, and should reflect the actual LSP status when files are being edited.
Steps to reproduce
- Open a project in OpenCode TUI with LSP support enabled
- Use an orchestrator agent that reads files (e.g., via the
read tool)
- Observe that files are being read and edited
- Check the LSP sidebar - it still shows "LSPs will activate as files are read" even though files have been processed
Root Cause Analysis
After investigating the code, I found the issue is in how LSP activation is triggered:
- The
read tool calls lsp.touchFile(filepath, false) via the warm function (src/tool/read.ts:81-84)
- This spawns LSP clients asynchronously using
Effect.forkIn(scope) - fire-and-forget
- When a new LSP client is created,
Bus.publish(Event.Updated, {}) is called (src/lsp/lsp.ts:314)
- This should trigger the TUI to refresh LSP status via the
lsp.updated event
The problem: The LSP activation happens asynchronously, and there's a race condition where:
- The sidebar checks
sync.data.lsp which is empty initially
- The LSP client is still being spawned in the background
- The event is published but the sidebar may not update correctly
- The message "LSPs will activate as files are read" persists even after activation
Additional Context
Looking at the code flow:
read.ts line 164: yield* warm(filepath) triggers LSP activation
lsp/lsp.ts line 314: Bus.publish(Event.Updated, {}) fires when client is added
sync.tsx line 310-313: Listens for lsp.updated and refreshes status
lsp.tsx line 36: Shows "LSPs will activate as files are read" when list().length === 0
The issue appears to be that the LSP status isn't being properly synchronized to the TUI state even after the event is published. This could be a timing issue or a problem with how the event is being handled in the plugin context.
Possible Solutions
- Ensure the LSP status is refreshed immediately after
touchFile completes, not just via the event bus
- Add a polling mechanism or force refresh when the sidebar is rendered
- Make the LSP activation synchronous for the first file read to ensure proper state initialization
- Add debugging/logging to trace the event flow from
Bus.publish to the TUI update
oh-my-opencode.json
OpenCode version
Latest upstream (anomalyco/opencode)
oh-my-opencode-slim version
Latest main branch
Operating system
macOS / Linux / Windows (all affected)
Logs, screenshots, or extra context
The issue is reproducible with the built-in opencode LSP integration when using orchestrator agents that read files programmatically. The LSP tool works correctly when called directly, but the automatic activation via file reads doesn't update the UI state properly.
What happened, and what did you expect?
What happened:
When using the OpenCode TUI with the orchestrator agent, the LSP sidebar continues to display "LSPs will activate as files are read" even after the orchestrator has read and edited multiple files in the project.
Expected behavior:
The LSP sidebar should update to show the connected LSP servers once files are read, and should reflect the actual LSP status when files are being edited.
Steps to reproduce
readtool)Root Cause Analysis
After investigating the code, I found the issue is in how LSP activation is triggered:
readtool callslsp.touchFile(filepath, false)via thewarmfunction (src/tool/read.ts:81-84)Effect.forkIn(scope)- fire-and-forgetBus.publish(Event.Updated, {})is called (src/lsp/lsp.ts:314)lsp.updatedeventThe problem: The LSP activation happens asynchronously, and there's a race condition where:
sync.data.lspwhich is empty initiallyAdditional Context
Looking at the code flow:
read.tsline 164:yield* warm(filepath)triggers LSP activationlsp/lsp.tsline 314:Bus.publish(Event.Updated, {})fires when client is addedsync.tsxline 310-313: Listens forlsp.updatedand refreshes statuslsp.tsxline 36: Shows "LSPs will activate as files are read" whenlist().length === 0The issue appears to be that the LSP status isn't being properly synchronized to the TUI state even after the event is published. This could be a timing issue or a problem with how the event is being handled in the plugin context.
Possible Solutions
touchFilecompletes, not just via the event busBus.publishto the TUI updateoh-my-opencode.json
// Default configuration, LSP enabledOpenCode version
Latest upstream (anomalyco/opencode)
oh-my-opencode-slim version
Latest main branch
Operating system
macOS / Linux / Windows (all affected)
Logs, screenshots, or extra context
The issue is reproducible with the built-in opencode LSP integration when using orchestrator agents that read files programmatically. The LSP tool works correctly when called directly, but the automatic activation via file reads doesn't update the UI state properly.