Skip to content
Open
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
9 changes: 9 additions & 0 deletions packages/opencode/src/server/shared/workspace-routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,14 @@ export function workspaceProxyURL(target: string | URL, requestURL: URL) {
proxyURL.search = requestURL.search
proxyURL.hash = requestURL.hash
proxyURL.searchParams.delete("workspace")
// The SDK rewrites the client's `x-opencode-directory` header into a
// `?directory=` query before sending. When the request is then proxied
// to a remote workspace, that local-machine path leaks through and the
// remote falls back to `worktree="/"` because the path doesn't exist on
// its filesystem — which corrupts downstream `path.relative()` callers
// (notably `sessionListQuery`) and wipes the TUI's session list.
// Strip it so the workspace adapter's `target.headers["x-opencode-directory"]`
// (the workspace's directory on the remote) wins.
proxyURL.searchParams.delete("directory")
return proxyURL
}
12 changes: 12 additions & 0 deletions packages/opencode/test/server/workspace-routing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ describe("workspaceProxyURL", () => {
expect(result.searchParams.get("keep")).toBe("yes")
})

test("strips directory query so the remote uses its own working directory", () => {
// The SDK rewrites the client's `x-opencode-directory` header into a
// `?directory=` query before sending. Forwarding that local-machine
// path to a remote workspace makes the remote fall back to
// `worktree="/"` (the path doesn't exist on its filesystem) and
// corrupts downstream `path.relative()` callers.
const url = new URL("http://localhost/path?workspace=ws_123&directory=%2FUsers%2Falice%2Fproj")
const result = workspaceProxyURL("http://remote:8080", url)
expect(result.searchParams.get("workspace")).toBeNull()
expect(result.searchParams.get("directory")).toBeNull()
})

test("preserves hash from request", () => {
const url = new URL("http://localhost/page#section")
const result = workspaceProxyURL("http://remote:8080", url)
Expand Down
Loading