fix(server): stop sending the local directory to a remote OpenCode server - #6228

Open
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory
Open

fix(server): stop sending the local directory to a remote OpenCode server#6228
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory

Conversation

@CDVolvik

@CDVolvikCDVolvik commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What Changed

createOpenCodeSdkClient no longer forwards the local directory to an OpenCode server that is both external and not on loopback. The client config moved into a pure buildOpenCodeSdkClientConfig so the decision is testable on its own, and the three callers pass the externality they already hold.

Why

Fixes#3094. All three call sites pass a local path unconditionally, so a Linux OpenCode server joins a Windows path onto its own and produces Invalid path /var/log/C:\Users\xxx. The error text comes from OpenCode's own bundle; what this repo controls is handing it a path that cannot mean anything on that host.

The obvious version of this fix — drop directory whenever server.external — is wrong, which is why the diff is a little larger than one line. Someone running OpenCode locally and pointing t3code at http://localhost:4096 is also external: true, and there the local directory is correct and useful. Dropping it would move those users to the server's own cwd and trade a loud bug for a quiet one. So localhost, 127.0.0.0/8, ::1, 0.0.0.0 and an unparseable base URL all keep the directory; a malformed setting cannot quietly change what the server receives.

The loopback narrowing is a heuristic and it is the one thing here I would rather you chose than me. If you would prefer an explicit setting, or a different definition of "remote", say which and I will change it.

Tests: 97/97 across the opencode and text-generation suites, tsgo --noEmit clean. Two new tests fail when the decision is reverted to always-send. Three others pass either way on purpose — they pin the local-external case, which is the regression the naive one-liner would have caused.

One honest limit: because buildOpenCodeSdkClientConfig is new, "fails without the fix" was demonstrated by reverting the decision and keeping the helper. Deleting the helper outright would only prove its own absence.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (none; server-side only)
  • I included a video for animation/interaction changes (none; server-side only)

Note

Medium Risk
Changes OpenCode connection and session-resume behavior for remote servers; loopback external URLs are explicitly preserved, but misclassified hostnames could still omit or send directory incorrectly.

Overview
Fixes #3094 by stopping the server from forwarding the client’s local directory to OpenCode when the target is an external, non-loopback host, which was producing invalid joined paths (e.g. Linux server + Windows cwd).

SDK client setup is centralized in buildOpenCodeSdkClientConfig with isLoopbackBaseUrl: directory is omitted only when external is true and the base URL is not localhost/127.x/::1 (unparseable URLs still send directory so misconfiguration does not silently drop it). Adapter, provider inventory, and text-generation paths pass external into createOpenCodeSdkClient.

Session resume in OpenCodeAdapter treats the same “remote” case as reusable without cwd comparison or session.fork, so resume no longer forks with a local path when the adopted session’s directory is server-side only. Local/managed behavior is unchanged.

Reviewed by Cursor Bugbot for commit 28715a9. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Stop sending local directory to remote OpenCode servers

  • Adds isLoopbackBaseUrl and buildOpenCodeSdkClientConfig in opencodeRuntime.ts so the SDK client omits the directory field for external, non-loopback servers while still sending auth headers
  • Updates startSession in OpenCodeAdapter.ts to treat adopted sessions from remote servers as reusable without comparing directories and to skip forking, only calling session.update to reassert permissions
  • Passes the external flag through all SDK client construction sites: inventory loading in OpenCodeProvider.ts and text generation in OpenCodeTextGeneration.ts
  • Behavioral Change: local directory is no longer included in SDK client config for remote servers; remote sessions are always reused rather than forked when a directory mismatch occurs

Macroscope summarized 28715a9.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ca0bfb4-e3dc-4cab-831c-3784097226fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Your free Security trial is over. An organization admin can activate Security or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 11, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 45e3645. Configure here.

Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — The PR is a focused OpenCode server bug fix with bounded runtime changes and targeted tests, preserving existing managed and loopback behavior. Open High-severity findings still identify risks in external client propagation and loopback classification, which independently require resolution under repository policy.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 45e3645 to f7cdd88CompareAugust 28, 2026 15:47
@CDVolvik

Copy link
Copy Markdown
ContributorAuthor

Fixed the resume gap flagged by Cursor Bugbot @ 45e3645.

What was still broken: After creating a remote session without \directory, the adopted session's server-side Linux path (e.g. /var/log) never equalled the local Windows \C:\Users...\ — so \sameDirectory\ returned false, resume took the fork path and re-sent the Windows directory via \session.fork, reproducing the same \Invalid path\ this PR was meant to fix.

Fix in f7cdd88:

  • Exported \isLoopbackBaseUrl\ from \opencodeRuntime.ts\ (same heuristic as \�uildOpenCodeSdkClientConfig) and imported it in \OpenCodeAdapter.ts.
  • For \server.external && !isLoopbackBaseUrl(server.url)\ (true remote) any adopted session is now treated as reusable without a cwd check, and the \session.fork\ branch is gated on !isRemote.
  • Rebased onto \upstream/main\ @ \

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 28, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review: one finding — the new remote-server branch in OpenCodeAdapter.startSession changes backend behavior but has no focused test. Client-config changes in opencodeRuntime.ts are covered by the new opencodeRuntime.sdkClient.test.ts.

Posted via Macroscope — Effect Service Conventions

Comment on lines +1272 to +1277
// For a remote server the local directory is meaningless — the
// client no longer sends it (#3094) and the adopted session's
// directory is a Linux path that will never equal the Windows
// one. Skip the cwd check and the fork entirely in that case
// so we don't reintroduce the Invalid path failure this PR fixes.
const isRemote = server.external && !isLoopbackBaseUrl(server.url);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes resume behavior for a remote server (skip the cwd comparison, never fork), but nothing exercises it: the existing suite configures serverUrl: "http://127.0.0.1:9999", which is loopback, so isRemote is always false and the new branch is never taken. Since this is a backend behavior change, consider adding a focused case in OpenCodeAdapter.test.ts with a non-loopback serverUrl (the runtime mock already returns external: Boolean(serverUrl)), asserting the adopted session is reused with forkCalls empty even when its directory differs.

Posted via Macroscope — Effect Service Conventions

normalized === "localhost" ||
normalized === "::1" ||
normalized === "0.0.0.0" ||
normalized.startsWith("127.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:209

isLoopbackBaseUrl misclassifies valid local endpoints such as localhost., name.localhost, and IPv4-mapped loopback [::ffff:127.0.0.1] as remote, so buildOpenCodeSdkClientConfig omits directory for them. It also classifies remote DNS names such as 127.example.com as loopback because of the textual 127. prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary 127.* DNS names as literals.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 209:
`isLoopbackBaseUrl` misclassifies valid local endpoints such as `localhost.`, `name.localhost`, and IPv4-mapped loopback `[::ffff:127.0.0.1]` as remote, so `buildOpenCodeSdkClientConfig` omits `directory` for them. It also classifies remote DNS names such as `127.example.com` as loopback because of the textual `127.` prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary `127.*` DNS names as literals.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from f7cdd88 to 59b7548CompareAugust 28, 2026 15:59
…rver
Connecting to an OpenCode server by URL from Windows failed to load models,
with the server reporting Invalid path /var/log/C:\Users\.... The client is
built with the local working directory and forwards it to whichever server is
on the other end, so a Windows path reached a Linux host and was joined onto
its own. The message comes from OpenCode itself; what we contribute is a path
that cannot mean anything there.
Only skip the directory when the server is externally configured AND its URL
is not loopback. External is not the same thing as remote: running OpenCode
locally and pointing the setting at http://localhost:4096 is also external,
and there the directory is correct and worth sending. Dropping it for those
users would trade a visible failure for a silent one, so localhost, 127.0.0.0/8,
::1 and 0.0.0.0 all keep it, as does a base URL that cannot be parsed.
The client config moves into a pure buildOpenCodeSdkClientConfig so the
decision is testable on its own, alongside the other exported helpers in this
module. Callers pass the externality they already know: the two adapter paths
forward server.external, which OpenCodeAdapter already branches on for the
authorization header, and the text-generation path uses the configured
serverUrl it already tests for the same purpose.
Follow-up: resume was still broken. After creating a session without a
directory, the adopted session's server-side directory never matched the
local Windows path, so the fork path reintroduced the same Invalid path
failure. For remote (external non-loopback) sessions the cwd check and fork
are now skipped entirely — any adopted session is reused in place.
isLoopbackBaseUrl is exported for the adapter to share the same heuristic.
Three of the five new tests cover the cases that must NOT change, and they
pass against the previous always-send behaviour as well, so they pin the
localhost case rather than the fix.
Fixespingdotgg#3094
@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 59b7548 to 28715a9CompareAugust 30, 2026 09:52
: {}),
throwOnError: true,
});
createOpencodeClient(buildOpenCodeSdkClientConfig(input));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:638

createOpenCodeSdkClient sends directory to external OpenCode servers because the external-server path in connectToOpenCodeServer does not set external: true. As a result, buildOpenCodeSdkClientConfig keeps sendDirectory true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass external: true when creating the client for the external-server branch.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 638:
`createOpenCodeSdkClient` sends `directory` to external OpenCode servers because the external-server path in `connectToOpenCodeServer` does not set `external: true`. As a result, `buildOpenCodeSdkClientConfig` keeps `sendDirectory` true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass `external: true` when creating the client for the external-server branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Connecting to a remote OpenCode server through URL running on Linux from a Windows machine does not work

1 participant

@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(server): stop sending the local directory to a remote OpenCode server - #6228

Open
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory
Open

fix(server): stop sending the local directory to a remote OpenCode server#6228
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory

Conversation

@CDVolvik

@CDVolvikCDVolvik commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What Changed

createOpenCodeSdkClient no longer forwards the local directory to an OpenCode server that is both external and not on loopback. The client config moved into a pure buildOpenCodeSdkClientConfig so the decision is testable on its own, and the three callers pass the externality they already hold.

Why

Fixes#3094. All three call sites pass a local path unconditionally, so a Linux OpenCode server joins a Windows path onto its own and produces Invalid path /var/log/C:\Users\xxx. The error text comes from OpenCode's own bundle; what this repo controls is handing it a path that cannot mean anything on that host.

The obvious version of this fix — drop directory whenever server.external — is wrong, which is why the diff is a little larger than one line. Someone running OpenCode locally and pointing t3code at http://localhost:4096 is also external: true, and there the local directory is correct and useful. Dropping it would move those users to the server's own cwd and trade a loud bug for a quiet one. So localhost, 127.0.0.0/8, ::1, 0.0.0.0 and an unparseable base URL all keep the directory; a malformed setting cannot quietly change what the server receives.

The loopback narrowing is a heuristic and it is the one thing here I would rather you chose than me. If you would prefer an explicit setting, or a different definition of "remote", say which and I will change it.

Tests: 97/97 across the opencode and text-generation suites, tsgo --noEmit clean. Two new tests fail when the decision is reverted to always-send. Three others pass either way on purpose — they pin the local-external case, which is the regression the naive one-liner would have caused.

One honest limit: because buildOpenCodeSdkClientConfig is new, "fails without the fix" was demonstrated by reverting the decision and keeping the helper. Deleting the helper outright would only prove its own absence.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (none; server-side only)
  • I included a video for animation/interaction changes (none; server-side only)

Note

Medium Risk
Changes OpenCode connection and session-resume behavior for remote servers; loopback external URLs are explicitly preserved, but misclassified hostnames could still omit or send directory incorrectly.

Overview
Fixes #3094 by stopping the server from forwarding the client’s local directory to OpenCode when the target is an external, non-loopback host, which was producing invalid joined paths (e.g. Linux server + Windows cwd).

SDK client setup is centralized in buildOpenCodeSdkClientConfig with isLoopbackBaseUrl: directory is omitted only when external is true and the base URL is not localhost/127.x/::1 (unparseable URLs still send directory so misconfiguration does not silently drop it). Adapter, provider inventory, and text-generation paths pass external into createOpenCodeSdkClient.

Session resume in OpenCodeAdapter treats the same “remote” case as reusable without cwd comparison or session.fork, so resume no longer forks with a local path when the adopted session’s directory is server-side only. Local/managed behavior is unchanged.

Reviewed by Cursor Bugbot for commit 28715a9. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Stop sending local directory to remote OpenCode servers

  • Adds isLoopbackBaseUrl and buildOpenCodeSdkClientConfig in opencodeRuntime.ts so the SDK client omits the directory field for external, non-loopback servers while still sending auth headers
  • Updates startSession in OpenCodeAdapter.ts to treat adopted sessions from remote servers as reusable without comparing directories and to skip forking, only calling session.update to reassert permissions
  • Passes the external flag through all SDK client construction sites: inventory loading in OpenCodeProvider.ts and text generation in OpenCodeTextGeneration.ts
  • Behavioral Change: local directory is no longer included in SDK client config for remote servers; remote sessions are always reused rather than forked when a directory mismatch occurs

Macroscope summarized 28715a9.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ca0bfb4-e3dc-4cab-831c-3784097226fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Your free Security trial is over. An organization admin can activate Security or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 11, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 45e3645. Configure here.

Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — The PR is a focused OpenCode server bug fix with bounded runtime changes and targeted tests, preserving existing managed and loopback behavior. Open High-severity findings still identify risks in external client propagation and loopback classification, which independently require resolution under repository policy.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 45e3645 to f7cdd88CompareAugust 28, 2026 15:47
@CDVolvik

Copy link
Copy Markdown
ContributorAuthor

Fixed the resume gap flagged by Cursor Bugbot @ 45e3645.

What was still broken: After creating a remote session without \directory, the adopted session's server-side Linux path (e.g. /var/log) never equalled the local Windows \C:\Users...\ — so \sameDirectory\ returned false, resume took the fork path and re-sent the Windows directory via \session.fork, reproducing the same \Invalid path\ this PR was meant to fix.

Fix in f7cdd88:

  • Exported \isLoopbackBaseUrl\ from \opencodeRuntime.ts\ (same heuristic as \�uildOpenCodeSdkClientConfig) and imported it in \OpenCodeAdapter.ts.
  • For \server.external && !isLoopbackBaseUrl(server.url)\ (true remote) any adopted session is now treated as reusable without a cwd check, and the \session.fork\ branch is gated on !isRemote.
  • Rebased onto \upstream/main\ @ \

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 28, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review: one finding — the new remote-server branch in OpenCodeAdapter.startSession changes backend behavior but has no focused test. Client-config changes in opencodeRuntime.ts are covered by the new opencodeRuntime.sdkClient.test.ts.

Posted via Macroscope — Effect Service Conventions

Comment on lines +1272 to +1277
// For a remote server the local directory is meaningless — the
// client no longer sends it (#3094) and the adopted session's
// directory is a Linux path that will never equal the Windows
// one. Skip the cwd check and the fork entirely in that case
// so we don't reintroduce the Invalid path failure this PR fixes.
const isRemote = server.external && !isLoopbackBaseUrl(server.url);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes resume behavior for a remote server (skip the cwd comparison, never fork), but nothing exercises it: the existing suite configures serverUrl: "http://127.0.0.1:9999", which is loopback, so isRemote is always false and the new branch is never taken. Since this is a backend behavior change, consider adding a focused case in OpenCodeAdapter.test.ts with a non-loopback serverUrl (the runtime mock already returns external: Boolean(serverUrl)), asserting the adopted session is reused with forkCalls empty even when its directory differs.

Posted via Macroscope — Effect Service Conventions

normalized === "localhost" ||
normalized === "::1" ||
normalized === "0.0.0.0" ||
normalized.startsWith("127.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:209

isLoopbackBaseUrl misclassifies valid local endpoints such as localhost., name.localhost, and IPv4-mapped loopback [::ffff:127.0.0.1] as remote, so buildOpenCodeSdkClientConfig omits directory for them. It also classifies remote DNS names such as 127.example.com as loopback because of the textual 127. prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary 127.* DNS names as literals.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 209:
`isLoopbackBaseUrl` misclassifies valid local endpoints such as `localhost.`, `name.localhost`, and IPv4-mapped loopback `[::ffff:127.0.0.1]` as remote, so `buildOpenCodeSdkClientConfig` omits `directory` for them. It also classifies remote DNS names such as `127.example.com` as loopback because of the textual `127.` prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary `127.*` DNS names as literals.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from f7cdd88 to 59b7548CompareAugust 28, 2026 15:59
…rver
Connecting to an OpenCode server by URL from Windows failed to load models,
with the server reporting Invalid path /var/log/C:\Users\.... The client is
built with the local working directory and forwards it to whichever server is
on the other end, so a Windows path reached a Linux host and was joined onto
its own. The message comes from OpenCode itself; what we contribute is a path
that cannot mean anything there.
Only skip the directory when the server is externally configured AND its URL
is not loopback. External is not the same thing as remote: running OpenCode
locally and pointing the setting at http://localhost:4096 is also external,
and there the directory is correct and worth sending. Dropping it for those
users would trade a visible failure for a silent one, so localhost, 127.0.0.0/8,
::1 and 0.0.0.0 all keep it, as does a base URL that cannot be parsed.
The client config moves into a pure buildOpenCodeSdkClientConfig so the
decision is testable on its own, alongside the other exported helpers in this
module. Callers pass the externality they already know: the two adapter paths
forward server.external, which OpenCodeAdapter already branches on for the
authorization header, and the text-generation path uses the configured
serverUrl it already tests for the same purpose.
Follow-up: resume was still broken. After creating a session without a
directory, the adopted session's server-side directory never matched the
local Windows path, so the fork path reintroduced the same Invalid path
failure. For remote (external non-loopback) sessions the cwd check and fork
are now skipped entirely — any adopted session is reused in place.
isLoopbackBaseUrl is exported for the adapter to share the same heuristic.
Three of the five new tests cover the cases that must NOT change, and they
pass against the previous always-send behaviour as well, so they pin the
localhost case rather than the fix.
Fixespingdotgg#3094
@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 59b7548 to 28715a9CompareAugust 30, 2026 09:52
: {}),
throwOnError: true,
});
createOpencodeClient(buildOpenCodeSdkClientConfig(input));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:638

createOpenCodeSdkClient sends directory to external OpenCode servers because the external-server path in connectToOpenCodeServer does not set external: true. As a result, buildOpenCodeSdkClientConfig keeps sendDirectory true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass external: true when creating the client for the external-server branch.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 638:
`createOpenCodeSdkClient` sends `directory` to external OpenCode servers because the external-server path in `connectToOpenCodeServer` does not set `external: true`. As a result, `buildOpenCodeSdkClientConfig` keeps `sendDirectory` true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass `external: true` when creating the client for the external-server branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Connecting to a remote OpenCode server through URL running on Linux from a Windows machine does not work

1 participant

@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(server): stop sending the local directory to a remote OpenCode server - #6228

Open
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory
Open

fix(server): stop sending the local directory to a remote OpenCode server#6228
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory

Conversation

@CDVolvik

@CDVolvikCDVolvik commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What Changed

createOpenCodeSdkClient no longer forwards the local directory to an OpenCode server that is both external and not on loopback. The client config moved into a pure buildOpenCodeSdkClientConfig so the decision is testable on its own, and the three callers pass the externality they already hold.

Why

Fixes#3094. All three call sites pass a local path unconditionally, so a Linux OpenCode server joins a Windows path onto its own and produces Invalid path /var/log/C:\Users\xxx. The error text comes from OpenCode's own bundle; what this repo controls is handing it a path that cannot mean anything on that host.

The obvious version of this fix — drop directory whenever server.external — is wrong, which is why the diff is a little larger than one line. Someone running OpenCode locally and pointing t3code at http://localhost:4096 is also external: true, and there the local directory is correct and useful. Dropping it would move those users to the server's own cwd and trade a loud bug for a quiet one. So localhost, 127.0.0.0/8, ::1, 0.0.0.0 and an unparseable base URL all keep the directory; a malformed setting cannot quietly change what the server receives.

The loopback narrowing is a heuristic and it is the one thing here I would rather you chose than me. If you would prefer an explicit setting, or a different definition of "remote", say which and I will change it.

Tests: 97/97 across the opencode and text-generation suites, tsgo --noEmit clean. Two new tests fail when the decision is reverted to always-send. Three others pass either way on purpose — they pin the local-external case, which is the regression the naive one-liner would have caused.

One honest limit: because buildOpenCodeSdkClientConfig is new, "fails without the fix" was demonstrated by reverting the decision and keeping the helper. Deleting the helper outright would only prove its own absence.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (none; server-side only)
  • I included a video for animation/interaction changes (none; server-side only)

Note

Medium Risk
Changes OpenCode connection and session-resume behavior for remote servers; loopback external URLs are explicitly preserved, but misclassified hostnames could still omit or send directory incorrectly.

Overview
Fixes #3094 by stopping the server from forwarding the client’s local directory to OpenCode when the target is an external, non-loopback host, which was producing invalid joined paths (e.g. Linux server + Windows cwd).

SDK client setup is centralized in buildOpenCodeSdkClientConfig with isLoopbackBaseUrl: directory is omitted only when external is true and the base URL is not localhost/127.x/::1 (unparseable URLs still send directory so misconfiguration does not silently drop it). Adapter, provider inventory, and text-generation paths pass external into createOpenCodeSdkClient.

Session resume in OpenCodeAdapter treats the same “remote” case as reusable without cwd comparison or session.fork, so resume no longer forks with a local path when the adopted session’s directory is server-side only. Local/managed behavior is unchanged.

Reviewed by Cursor Bugbot for commit 28715a9. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Stop sending local directory to remote OpenCode servers

  • Adds isLoopbackBaseUrl and buildOpenCodeSdkClientConfig in opencodeRuntime.ts so the SDK client omits the directory field for external, non-loopback servers while still sending auth headers
  • Updates startSession in OpenCodeAdapter.ts to treat adopted sessions from remote servers as reusable without comparing directories and to skip forking, only calling session.update to reassert permissions
  • Passes the external flag through all SDK client construction sites: inventory loading in OpenCodeProvider.ts and text generation in OpenCodeTextGeneration.ts
  • Behavioral Change: local directory is no longer included in SDK client config for remote servers; remote sessions are always reused rather than forked when a directory mismatch occurs

Macroscope summarized 28715a9.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ca0bfb4-e3dc-4cab-831c-3784097226fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Your free Security trial is over. An organization admin can activate Security or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 11, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 45e3645. Configure here.

Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — The PR is a focused OpenCode server bug fix with bounded runtime changes and targeted tests, preserving existing managed and loopback behavior. Open High-severity findings still identify risks in external client propagation and loopback classification, which independently require resolution under repository policy.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 45e3645 to f7cdd88CompareAugust 28, 2026 15:47
@CDVolvik

Copy link
Copy Markdown
ContributorAuthor

Fixed the resume gap flagged by Cursor Bugbot @ 45e3645.

What was still broken: After creating a remote session without \directory, the adopted session's server-side Linux path (e.g. /var/log) never equalled the local Windows \C:\Users...\ — so \sameDirectory\ returned false, resume took the fork path and re-sent the Windows directory via \session.fork, reproducing the same \Invalid path\ this PR was meant to fix.

Fix in f7cdd88:

  • Exported \isLoopbackBaseUrl\ from \opencodeRuntime.ts\ (same heuristic as \�uildOpenCodeSdkClientConfig) and imported it in \OpenCodeAdapter.ts.
  • For \server.external && !isLoopbackBaseUrl(server.url)\ (true remote) any adopted session is now treated as reusable without a cwd check, and the \session.fork\ branch is gated on !isRemote.
  • Rebased onto \upstream/main\ @ \

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 28, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review: one finding — the new remote-server branch in OpenCodeAdapter.startSession changes backend behavior but has no focused test. Client-config changes in opencodeRuntime.ts are covered by the new opencodeRuntime.sdkClient.test.ts.

Posted via Macroscope — Effect Service Conventions

Comment on lines +1272 to +1277
// For a remote server the local directory is meaningless — the
// client no longer sends it (#3094) and the adopted session's
// directory is a Linux path that will never equal the Windows
// one. Skip the cwd check and the fork entirely in that case
// so we don't reintroduce the Invalid path failure this PR fixes.
const isRemote = server.external && !isLoopbackBaseUrl(server.url);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes resume behavior for a remote server (skip the cwd comparison, never fork), but nothing exercises it: the existing suite configures serverUrl: "http://127.0.0.1:9999", which is loopback, so isRemote is always false and the new branch is never taken. Since this is a backend behavior change, consider adding a focused case in OpenCodeAdapter.test.ts with a non-loopback serverUrl (the runtime mock already returns external: Boolean(serverUrl)), asserting the adopted session is reused with forkCalls empty even when its directory differs.

Posted via Macroscope — Effect Service Conventions

normalized === "localhost" ||
normalized === "::1" ||
normalized === "0.0.0.0" ||
normalized.startsWith("127.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:209

isLoopbackBaseUrl misclassifies valid local endpoints such as localhost., name.localhost, and IPv4-mapped loopback [::ffff:127.0.0.1] as remote, so buildOpenCodeSdkClientConfig omits directory for them. It also classifies remote DNS names such as 127.example.com as loopback because of the textual 127. prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary 127.* DNS names as literals.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 209:
`isLoopbackBaseUrl` misclassifies valid local endpoints such as `localhost.`, `name.localhost`, and IPv4-mapped loopback `[::ffff:127.0.0.1]` as remote, so `buildOpenCodeSdkClientConfig` omits `directory` for them. It also classifies remote DNS names such as `127.example.com` as loopback because of the textual `127.` prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary `127.*` DNS names as literals.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from f7cdd88 to 59b7548CompareAugust 28, 2026 15:59
…rver
Connecting to an OpenCode server by URL from Windows failed to load models,
with the server reporting Invalid path /var/log/C:\Users\.... The client is
built with the local working directory and forwards it to whichever server is
on the other end, so a Windows path reached a Linux host and was joined onto
its own. The message comes from OpenCode itself; what we contribute is a path
that cannot mean anything there.
Only skip the directory when the server is externally configured AND its URL
is not loopback. External is not the same thing as remote: running OpenCode
locally and pointing the setting at http://localhost:4096 is also external,
and there the directory is correct and worth sending. Dropping it for those
users would trade a visible failure for a silent one, so localhost, 127.0.0.0/8,
::1 and 0.0.0.0 all keep it, as does a base URL that cannot be parsed.
The client config moves into a pure buildOpenCodeSdkClientConfig so the
decision is testable on its own, alongside the other exported helpers in this
module. Callers pass the externality they already know: the two adapter paths
forward server.external, which OpenCodeAdapter already branches on for the
authorization header, and the text-generation path uses the configured
serverUrl it already tests for the same purpose.
Follow-up: resume was still broken. After creating a session without a
directory, the adopted session's server-side directory never matched the
local Windows path, so the fork path reintroduced the same Invalid path
failure. For remote (external non-loopback) sessions the cwd check and fork
are now skipped entirely — any adopted session is reused in place.
isLoopbackBaseUrl is exported for the adapter to share the same heuristic.
Three of the five new tests cover the cases that must NOT change, and they
pass against the previous always-send behaviour as well, so they pin the
localhost case rather than the fix.
Fixespingdotgg#3094
@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 59b7548 to 28715a9CompareAugust 30, 2026 09:52
: {}),
throwOnError: true,
});
createOpencodeClient(buildOpenCodeSdkClientConfig(input));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:638

createOpenCodeSdkClient sends directory to external OpenCode servers because the external-server path in connectToOpenCodeServer does not set external: true. As a result, buildOpenCodeSdkClientConfig keeps sendDirectory true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass external: true when creating the client for the external-server branch.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 638:
`createOpenCodeSdkClient` sends `directory` to external OpenCode servers because the external-server path in `connectToOpenCodeServer` does not set `external: true`. As a result, `buildOpenCodeSdkClientConfig` keeps `sendDirectory` true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass `external: true` when creating the client for the external-server branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Connecting to a remote OpenCode server through URL running on Linux from a Windows machine does not work

1 participant

@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(server): stop sending the local directory to a remote OpenCode server - #6228

Open
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory
Open

fix(server): stop sending the local directory to a remote OpenCode server#6228
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory

Conversation

@CDVolvik

@CDVolvikCDVolvik commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What Changed

createOpenCodeSdkClient no longer forwards the local directory to an OpenCode server that is both external and not on loopback. The client config moved into a pure buildOpenCodeSdkClientConfig so the decision is testable on its own, and the three callers pass the externality they already hold.

Why

Fixes#3094. All three call sites pass a local path unconditionally, so a Linux OpenCode server joins a Windows path onto its own and produces Invalid path /var/log/C:\Users\xxx. The error text comes from OpenCode's own bundle; what this repo controls is handing it a path that cannot mean anything on that host.

The obvious version of this fix — drop directory whenever server.external — is wrong, which is why the diff is a little larger than one line. Someone running OpenCode locally and pointing t3code at http://localhost:4096 is also external: true, and there the local directory is correct and useful. Dropping it would move those users to the server's own cwd and trade a loud bug for a quiet one. So localhost, 127.0.0.0/8, ::1, 0.0.0.0 and an unparseable base URL all keep the directory; a malformed setting cannot quietly change what the server receives.

The loopback narrowing is a heuristic and it is the one thing here I would rather you chose than me. If you would prefer an explicit setting, or a different definition of "remote", say which and I will change it.

Tests: 97/97 across the opencode and text-generation suites, tsgo --noEmit clean. Two new tests fail when the decision is reverted to always-send. Three others pass either way on purpose — they pin the local-external case, which is the regression the naive one-liner would have caused.

One honest limit: because buildOpenCodeSdkClientConfig is new, "fails without the fix" was demonstrated by reverting the decision and keeping the helper. Deleting the helper outright would only prove its own absence.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (none; server-side only)
  • I included a video for animation/interaction changes (none; server-side only)

Note

Medium Risk
Changes OpenCode connection and session-resume behavior for remote servers; loopback external URLs are explicitly preserved, but misclassified hostnames could still omit or send directory incorrectly.

Overview
Fixes #3094 by stopping the server from forwarding the client’s local directory to OpenCode when the target is an external, non-loopback host, which was producing invalid joined paths (e.g. Linux server + Windows cwd).

SDK client setup is centralized in buildOpenCodeSdkClientConfig with isLoopbackBaseUrl: directory is omitted only when external is true and the base URL is not localhost/127.x/::1 (unparseable URLs still send directory so misconfiguration does not silently drop it). Adapter, provider inventory, and text-generation paths pass external into createOpenCodeSdkClient.

Session resume in OpenCodeAdapter treats the same “remote” case as reusable without cwd comparison or session.fork, so resume no longer forks with a local path when the adopted session’s directory is server-side only. Local/managed behavior is unchanged.

Reviewed by Cursor Bugbot for commit 28715a9. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Stop sending local directory to remote OpenCode servers

  • Adds isLoopbackBaseUrl and buildOpenCodeSdkClientConfig in opencodeRuntime.ts so the SDK client omits the directory field for external, non-loopback servers while still sending auth headers
  • Updates startSession in OpenCodeAdapter.ts to treat adopted sessions from remote servers as reusable without comparing directories and to skip forking, only calling session.update to reassert permissions
  • Passes the external flag through all SDK client construction sites: inventory loading in OpenCodeProvider.ts and text generation in OpenCodeTextGeneration.ts
  • Behavioral Change: local directory is no longer included in SDK client config for remote servers; remote sessions are always reused rather than forked when a directory mismatch occurs

Macroscope summarized 28715a9.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ca0bfb4-e3dc-4cab-831c-3784097226fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Your free Security trial is over. An organization admin can activate Security or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 11, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 45e3645. Configure here.

Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — The PR is a focused OpenCode server bug fix with bounded runtime changes and targeted tests, preserving existing managed and loopback behavior. Open High-severity findings still identify risks in external client propagation and loopback classification, which independently require resolution under repository policy.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 45e3645 to f7cdd88CompareAugust 28, 2026 15:47
@CDVolvik

Copy link
Copy Markdown
ContributorAuthor

Fixed the resume gap flagged by Cursor Bugbot @ 45e3645.

What was still broken: After creating a remote session without \directory, the adopted session's server-side Linux path (e.g. /var/log) never equalled the local Windows \C:\Users...\ — so \sameDirectory\ returned false, resume took the fork path and re-sent the Windows directory via \session.fork, reproducing the same \Invalid path\ this PR was meant to fix.

Fix in f7cdd88:

  • Exported \isLoopbackBaseUrl\ from \opencodeRuntime.ts\ (same heuristic as \�uildOpenCodeSdkClientConfig) and imported it in \OpenCodeAdapter.ts.
  • For \server.external && !isLoopbackBaseUrl(server.url)\ (true remote) any adopted session is now treated as reusable without a cwd check, and the \session.fork\ branch is gated on !isRemote.
  • Rebased onto \upstream/main\ @ \

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 28, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review: one finding — the new remote-server branch in OpenCodeAdapter.startSession changes backend behavior but has no focused test. Client-config changes in opencodeRuntime.ts are covered by the new opencodeRuntime.sdkClient.test.ts.

Posted via Macroscope — Effect Service Conventions

Comment on lines +1272 to +1277
// For a remote server the local directory is meaningless — the
// client no longer sends it (#3094) and the adopted session's
// directory is a Linux path that will never equal the Windows
// one. Skip the cwd check and the fork entirely in that case
// so we don't reintroduce the Invalid path failure this PR fixes.
const isRemote = server.external && !isLoopbackBaseUrl(server.url);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes resume behavior for a remote server (skip the cwd comparison, never fork), but nothing exercises it: the existing suite configures serverUrl: "http://127.0.0.1:9999", which is loopback, so isRemote is always false and the new branch is never taken. Since this is a backend behavior change, consider adding a focused case in OpenCodeAdapter.test.ts with a non-loopback serverUrl (the runtime mock already returns external: Boolean(serverUrl)), asserting the adopted session is reused with forkCalls empty even when its directory differs.

Posted via Macroscope — Effect Service Conventions

normalized === "localhost" ||
normalized === "::1" ||
normalized === "0.0.0.0" ||
normalized.startsWith("127.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:209

isLoopbackBaseUrl misclassifies valid local endpoints such as localhost., name.localhost, and IPv4-mapped loopback [::ffff:127.0.0.1] as remote, so buildOpenCodeSdkClientConfig omits directory for them. It also classifies remote DNS names such as 127.example.com as loopback because of the textual 127. prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary 127.* DNS names as literals.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 209:
`isLoopbackBaseUrl` misclassifies valid local endpoints such as `localhost.`, `name.localhost`, and IPv4-mapped loopback `[::ffff:127.0.0.1]` as remote, so `buildOpenCodeSdkClientConfig` omits `directory` for them. It also classifies remote DNS names such as `127.example.com` as loopback because of the textual `127.` prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary `127.*` DNS names as literals.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from f7cdd88 to 59b7548CompareAugust 28, 2026 15:59
…rver
Connecting to an OpenCode server by URL from Windows failed to load models,
with the server reporting Invalid path /var/log/C:\Users\.... The client is
built with the local working directory and forwards it to whichever server is
on the other end, so a Windows path reached a Linux host and was joined onto
its own. The message comes from OpenCode itself; what we contribute is a path
that cannot mean anything there.
Only skip the directory when the server is externally configured AND its URL
is not loopback. External is not the same thing as remote: running OpenCode
locally and pointing the setting at http://localhost:4096 is also external,
and there the directory is correct and worth sending. Dropping it for those
users would trade a visible failure for a silent one, so localhost, 127.0.0.0/8,
::1 and 0.0.0.0 all keep it, as does a base URL that cannot be parsed.
The client config moves into a pure buildOpenCodeSdkClientConfig so the
decision is testable on its own, alongside the other exported helpers in this
module. Callers pass the externality they already know: the two adapter paths
forward server.external, which OpenCodeAdapter already branches on for the
authorization header, and the text-generation path uses the configured
serverUrl it already tests for the same purpose.
Follow-up: resume was still broken. After creating a session without a
directory, the adopted session's server-side directory never matched the
local Windows path, so the fork path reintroduced the same Invalid path
failure. For remote (external non-loopback) sessions the cwd check and fork
are now skipped entirely — any adopted session is reused in place.
isLoopbackBaseUrl is exported for the adapter to share the same heuristic.
Three of the five new tests cover the cases that must NOT change, and they
pass against the previous always-send behaviour as well, so they pin the
localhost case rather than the fix.
Fixespingdotgg#3094
@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 59b7548 to 28715a9CompareAugust 30, 2026 09:52
: {}),
throwOnError: true,
});
createOpencodeClient(buildOpenCodeSdkClientConfig(input));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:638

createOpenCodeSdkClient sends directory to external OpenCode servers because the external-server path in connectToOpenCodeServer does not set external: true. As a result, buildOpenCodeSdkClientConfig keeps sendDirectory true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass external: true when creating the client for the external-server branch.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 638:
`createOpenCodeSdkClient` sends `directory` to external OpenCode servers because the external-server path in `connectToOpenCodeServer` does not set `external: true`. As a result, `buildOpenCodeSdkClientConfig` keeps `sendDirectory` true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass `external: true` when creating the client for the external-server branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Connecting to a remote OpenCode server through URL running on Linux from a Windows machine does not work

1 participant

@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(server): stop sending the local directory to a remote OpenCode server - #6228

Open
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory
Open

fix(server): stop sending the local directory to a remote OpenCode server#6228
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory

Conversation

@CDVolvik

@CDVolvikCDVolvik commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What Changed

createOpenCodeSdkClient no longer forwards the local directory to an OpenCode server that is both external and not on loopback. The client config moved into a pure buildOpenCodeSdkClientConfig so the decision is testable on its own, and the three callers pass the externality they already hold.

Why

Fixes#3094. All three call sites pass a local path unconditionally, so a Linux OpenCode server joins a Windows path onto its own and produces Invalid path /var/log/C:\Users\xxx. The error text comes from OpenCode's own bundle; what this repo controls is handing it a path that cannot mean anything on that host.

The obvious version of this fix — drop directory whenever server.external — is wrong, which is why the diff is a little larger than one line. Someone running OpenCode locally and pointing t3code at http://localhost:4096 is also external: true, and there the local directory is correct and useful. Dropping it would move those users to the server's own cwd and trade a loud bug for a quiet one. So localhost, 127.0.0.0/8, ::1, 0.0.0.0 and an unparseable base URL all keep the directory; a malformed setting cannot quietly change what the server receives.

The loopback narrowing is a heuristic and it is the one thing here I would rather you chose than me. If you would prefer an explicit setting, or a different definition of "remote", say which and I will change it.

Tests: 97/97 across the opencode and text-generation suites, tsgo --noEmit clean. Two new tests fail when the decision is reverted to always-send. Three others pass either way on purpose — they pin the local-external case, which is the regression the naive one-liner would have caused.

One honest limit: because buildOpenCodeSdkClientConfig is new, "fails without the fix" was demonstrated by reverting the decision and keeping the helper. Deleting the helper outright would only prove its own absence.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (none; server-side only)
  • I included a video for animation/interaction changes (none; server-side only)

Note

Medium Risk
Changes OpenCode connection and session-resume behavior for remote servers; loopback external URLs are explicitly preserved, but misclassified hostnames could still omit or send directory incorrectly.

Overview
Fixes #3094 by stopping the server from forwarding the client’s local directory to OpenCode when the target is an external, non-loopback host, which was producing invalid joined paths (e.g. Linux server + Windows cwd).

SDK client setup is centralized in buildOpenCodeSdkClientConfig with isLoopbackBaseUrl: directory is omitted only when external is true and the base URL is not localhost/127.x/::1 (unparseable URLs still send directory so misconfiguration does not silently drop it). Adapter, provider inventory, and text-generation paths pass external into createOpenCodeSdkClient.

Session resume in OpenCodeAdapter treats the same “remote” case as reusable without cwd comparison or session.fork, so resume no longer forks with a local path when the adopted session’s directory is server-side only. Local/managed behavior is unchanged.

Reviewed by Cursor Bugbot for commit 28715a9. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Stop sending local directory to remote OpenCode servers

  • Adds isLoopbackBaseUrl and buildOpenCodeSdkClientConfig in opencodeRuntime.ts so the SDK client omits the directory field for external, non-loopback servers while still sending auth headers
  • Updates startSession in OpenCodeAdapter.ts to treat adopted sessions from remote servers as reusable without comparing directories and to skip forking, only calling session.update to reassert permissions
  • Passes the external flag through all SDK client construction sites: inventory loading in OpenCodeProvider.ts and text generation in OpenCodeTextGeneration.ts
  • Behavioral Change: local directory is no longer included in SDK client config for remote servers; remote sessions are always reused rather than forked when a directory mismatch occurs

Macroscope summarized 28715a9.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ca0bfb4-e3dc-4cab-831c-3784097226fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Your free Security trial is over. An organization admin can activate Security or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 11, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 45e3645. Configure here.

Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — The PR is a focused OpenCode server bug fix with bounded runtime changes and targeted tests, preserving existing managed and loopback behavior. Open High-severity findings still identify risks in external client propagation and loopback classification, which independently require resolution under repository policy.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 45e3645 to f7cdd88CompareAugust 28, 2026 15:47
@CDVolvik

Copy link
Copy Markdown
ContributorAuthor

Fixed the resume gap flagged by Cursor Bugbot @ 45e3645.

What was still broken: After creating a remote session without \directory, the adopted session's server-side Linux path (e.g. /var/log) never equalled the local Windows \C:\Users...\ — so \sameDirectory\ returned false, resume took the fork path and re-sent the Windows directory via \session.fork, reproducing the same \Invalid path\ this PR was meant to fix.

Fix in f7cdd88:

  • Exported \isLoopbackBaseUrl\ from \opencodeRuntime.ts\ (same heuristic as \�uildOpenCodeSdkClientConfig) and imported it in \OpenCodeAdapter.ts.
  • For \server.external && !isLoopbackBaseUrl(server.url)\ (true remote) any adopted session is now treated as reusable without a cwd check, and the \session.fork\ branch is gated on !isRemote.
  • Rebased onto \upstream/main\ @ \

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 28, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review: one finding — the new remote-server branch in OpenCodeAdapter.startSession changes backend behavior but has no focused test. Client-config changes in opencodeRuntime.ts are covered by the new opencodeRuntime.sdkClient.test.ts.

Posted via Macroscope — Effect Service Conventions

Comment on lines +1272 to +1277
// For a remote server the local directory is meaningless — the
// client no longer sends it (#3094) and the adopted session's
// directory is a Linux path that will never equal the Windows
// one. Skip the cwd check and the fork entirely in that case
// so we don't reintroduce the Invalid path failure this PR fixes.
const isRemote = server.external && !isLoopbackBaseUrl(server.url);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes resume behavior for a remote server (skip the cwd comparison, never fork), but nothing exercises it: the existing suite configures serverUrl: "http://127.0.0.1:9999", which is loopback, so isRemote is always false and the new branch is never taken. Since this is a backend behavior change, consider adding a focused case in OpenCodeAdapter.test.ts with a non-loopback serverUrl (the runtime mock already returns external: Boolean(serverUrl)), asserting the adopted session is reused with forkCalls empty even when its directory differs.

Posted via Macroscope — Effect Service Conventions

normalized === "localhost" ||
normalized === "::1" ||
normalized === "0.0.0.0" ||
normalized.startsWith("127.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:209

isLoopbackBaseUrl misclassifies valid local endpoints such as localhost., name.localhost, and IPv4-mapped loopback [::ffff:127.0.0.1] as remote, so buildOpenCodeSdkClientConfig omits directory for them. It also classifies remote DNS names such as 127.example.com as loopback because of the textual 127. prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary 127.* DNS names as literals.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 209:
`isLoopbackBaseUrl` misclassifies valid local endpoints such as `localhost.`, `name.localhost`, and IPv4-mapped loopback `[::ffff:127.0.0.1]` as remote, so `buildOpenCodeSdkClientConfig` omits `directory` for them. It also classifies remote DNS names such as `127.example.com` as loopback because of the textual `127.` prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary `127.*` DNS names as literals.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from f7cdd88 to 59b7548CompareAugust 28, 2026 15:59
…rver
Connecting to an OpenCode server by URL from Windows failed to load models,
with the server reporting Invalid path /var/log/C:\Users\.... The client is
built with the local working directory and forwards it to whichever server is
on the other end, so a Windows path reached a Linux host and was joined onto
its own. The message comes from OpenCode itself; what we contribute is a path
that cannot mean anything there.
Only skip the directory when the server is externally configured AND its URL
is not loopback. External is not the same thing as remote: running OpenCode
locally and pointing the setting at http://localhost:4096 is also external,
and there the directory is correct and worth sending. Dropping it for those
users would trade a visible failure for a silent one, so localhost, 127.0.0.0/8,
::1 and 0.0.0.0 all keep it, as does a base URL that cannot be parsed.
The client config moves into a pure buildOpenCodeSdkClientConfig so the
decision is testable on its own, alongside the other exported helpers in this
module. Callers pass the externality they already know: the two adapter paths
forward server.external, which OpenCodeAdapter already branches on for the
authorization header, and the text-generation path uses the configured
serverUrl it already tests for the same purpose.
Follow-up: resume was still broken. After creating a session without a
directory, the adopted session's server-side directory never matched the
local Windows path, so the fork path reintroduced the same Invalid path
failure. For remote (external non-loopback) sessions the cwd check and fork
are now skipped entirely — any adopted session is reused in place.
isLoopbackBaseUrl is exported for the adapter to share the same heuristic.
Three of the five new tests cover the cases that must NOT change, and they
pass against the previous always-send behaviour as well, so they pin the
localhost case rather than the fix.
Fixespingdotgg#3094
@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 59b7548 to 28715a9CompareAugust 30, 2026 09:52
: {}),
throwOnError: true,
});
createOpencodeClient(buildOpenCodeSdkClientConfig(input));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:638

createOpenCodeSdkClient sends directory to external OpenCode servers because the external-server path in connectToOpenCodeServer does not set external: true. As a result, buildOpenCodeSdkClientConfig keeps sendDirectory true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass external: true when creating the client for the external-server branch.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 638:
`createOpenCodeSdkClient` sends `directory` to external OpenCode servers because the external-server path in `connectToOpenCodeServer` does not set `external: true`. As a result, `buildOpenCodeSdkClientConfig` keeps `sendDirectory` true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass `external: true` when creating the client for the external-server branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Connecting to a remote OpenCode server through URL running on Linux from a Windows machine does not work

1 participant

@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(server): stop sending the local directory to a remote OpenCode server - #6228

Open
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory
Open

fix(server): stop sending the local directory to a remote OpenCode server#6228
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory

Conversation

@CDVolvik

@CDVolvikCDVolvik commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What Changed

createOpenCodeSdkClient no longer forwards the local directory to an OpenCode server that is both external and not on loopback. The client config moved into a pure buildOpenCodeSdkClientConfig so the decision is testable on its own, and the three callers pass the externality they already hold.

Why

Fixes#3094. All three call sites pass a local path unconditionally, so a Linux OpenCode server joins a Windows path onto its own and produces Invalid path /var/log/C:\Users\xxx. The error text comes from OpenCode's own bundle; what this repo controls is handing it a path that cannot mean anything on that host.

The obvious version of this fix — drop directory whenever server.external — is wrong, which is why the diff is a little larger than one line. Someone running OpenCode locally and pointing t3code at http://localhost:4096 is also external: true, and there the local directory is correct and useful. Dropping it would move those users to the server's own cwd and trade a loud bug for a quiet one. So localhost, 127.0.0.0/8, ::1, 0.0.0.0 and an unparseable base URL all keep the directory; a malformed setting cannot quietly change what the server receives.

The loopback narrowing is a heuristic and it is the one thing here I would rather you chose than me. If you would prefer an explicit setting, or a different definition of "remote", say which and I will change it.

Tests: 97/97 across the opencode and text-generation suites, tsgo --noEmit clean. Two new tests fail when the decision is reverted to always-send. Three others pass either way on purpose — they pin the local-external case, which is the regression the naive one-liner would have caused.

One honest limit: because buildOpenCodeSdkClientConfig is new, "fails without the fix" was demonstrated by reverting the decision and keeping the helper. Deleting the helper outright would only prove its own absence.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (none; server-side only)
  • I included a video for animation/interaction changes (none; server-side only)

Note

Medium Risk
Changes OpenCode connection and session-resume behavior for remote servers; loopback external URLs are explicitly preserved, but misclassified hostnames could still omit or send directory incorrectly.

Overview
Fixes #3094 by stopping the server from forwarding the client’s local directory to OpenCode when the target is an external, non-loopback host, which was producing invalid joined paths (e.g. Linux server + Windows cwd).

SDK client setup is centralized in buildOpenCodeSdkClientConfig with isLoopbackBaseUrl: directory is omitted only when external is true and the base URL is not localhost/127.x/::1 (unparseable URLs still send directory so misconfiguration does not silently drop it). Adapter, provider inventory, and text-generation paths pass external into createOpenCodeSdkClient.

Session resume in OpenCodeAdapter treats the same “remote” case as reusable without cwd comparison or session.fork, so resume no longer forks with a local path when the adopted session’s directory is server-side only. Local/managed behavior is unchanged.

Reviewed by Cursor Bugbot for commit 28715a9. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Stop sending local directory to remote OpenCode servers

  • Adds isLoopbackBaseUrl and buildOpenCodeSdkClientConfig in opencodeRuntime.ts so the SDK client omits the directory field for external, non-loopback servers while still sending auth headers
  • Updates startSession in OpenCodeAdapter.ts to treat adopted sessions from remote servers as reusable without comparing directories and to skip forking, only calling session.update to reassert permissions
  • Passes the external flag through all SDK client construction sites: inventory loading in OpenCodeProvider.ts and text generation in OpenCodeTextGeneration.ts
  • Behavioral Change: local directory is no longer included in SDK client config for remote servers; remote sessions are always reused rather than forked when a directory mismatch occurs

Macroscope summarized 28715a9.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ca0bfb4-e3dc-4cab-831c-3784097226fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Your free Security trial is over. An organization admin can activate Security or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 11, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 45e3645. Configure here.

Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — The PR is a focused OpenCode server bug fix with bounded runtime changes and targeted tests, preserving existing managed and loopback behavior. Open High-severity findings still identify risks in external client propagation and loopback classification, which independently require resolution under repository policy.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 45e3645 to f7cdd88CompareAugust 28, 2026 15:47
@CDVolvik

Copy link
Copy Markdown
ContributorAuthor

Fixed the resume gap flagged by Cursor Bugbot @ 45e3645.

What was still broken: After creating a remote session without \directory, the adopted session's server-side Linux path (e.g. /var/log) never equalled the local Windows \C:\Users...\ — so \sameDirectory\ returned false, resume took the fork path and re-sent the Windows directory via \session.fork, reproducing the same \Invalid path\ this PR was meant to fix.

Fix in f7cdd88:

  • Exported \isLoopbackBaseUrl\ from \opencodeRuntime.ts\ (same heuristic as \�uildOpenCodeSdkClientConfig) and imported it in \OpenCodeAdapter.ts.
  • For \server.external && !isLoopbackBaseUrl(server.url)\ (true remote) any adopted session is now treated as reusable without a cwd check, and the \session.fork\ branch is gated on !isRemote.
  • Rebased onto \upstream/main\ @ \

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 28, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review: one finding — the new remote-server branch in OpenCodeAdapter.startSession changes backend behavior but has no focused test. Client-config changes in opencodeRuntime.ts are covered by the new opencodeRuntime.sdkClient.test.ts.

Posted via Macroscope — Effect Service Conventions

Comment on lines +1272 to +1277
// For a remote server the local directory is meaningless — the
// client no longer sends it (#3094) and the adopted session's
// directory is a Linux path that will never equal the Windows
// one. Skip the cwd check and the fork entirely in that case
// so we don't reintroduce the Invalid path failure this PR fixes.
const isRemote = server.external && !isLoopbackBaseUrl(server.url);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes resume behavior for a remote server (skip the cwd comparison, never fork), but nothing exercises it: the existing suite configures serverUrl: "http://127.0.0.1:9999", which is loopback, so isRemote is always false and the new branch is never taken. Since this is a backend behavior change, consider adding a focused case in OpenCodeAdapter.test.ts with a non-loopback serverUrl (the runtime mock already returns external: Boolean(serverUrl)), asserting the adopted session is reused with forkCalls empty even when its directory differs.

Posted via Macroscope — Effect Service Conventions

normalized === "localhost" ||
normalized === "::1" ||
normalized === "0.0.0.0" ||
normalized.startsWith("127.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:209

isLoopbackBaseUrl misclassifies valid local endpoints such as localhost., name.localhost, and IPv4-mapped loopback [::ffff:127.0.0.1] as remote, so buildOpenCodeSdkClientConfig omits directory for them. It also classifies remote DNS names such as 127.example.com as loopback because of the textual 127. prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary 127.* DNS names as literals.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 209:
`isLoopbackBaseUrl` misclassifies valid local endpoints such as `localhost.`, `name.localhost`, and IPv4-mapped loopback `[::ffff:127.0.0.1]` as remote, so `buildOpenCodeSdkClientConfig` omits `directory` for them. It also classifies remote DNS names such as `127.example.com` as loopback because of the textual `127.` prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary `127.*` DNS names as literals.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from f7cdd88 to 59b7548CompareAugust 28, 2026 15:59
…rver
Connecting to an OpenCode server by URL from Windows failed to load models,
with the server reporting Invalid path /var/log/C:\Users\.... The client is
built with the local working directory and forwards it to whichever server is
on the other end, so a Windows path reached a Linux host and was joined onto
its own. The message comes from OpenCode itself; what we contribute is a path
that cannot mean anything there.
Only skip the directory when the server is externally configured AND its URL
is not loopback. External is not the same thing as remote: running OpenCode
locally and pointing the setting at http://localhost:4096 is also external,
and there the directory is correct and worth sending. Dropping it for those
users would trade a visible failure for a silent one, so localhost, 127.0.0.0/8,
::1 and 0.0.0.0 all keep it, as does a base URL that cannot be parsed.
The client config moves into a pure buildOpenCodeSdkClientConfig so the
decision is testable on its own, alongside the other exported helpers in this
module. Callers pass the externality they already know: the two adapter paths
forward server.external, which OpenCodeAdapter already branches on for the
authorization header, and the text-generation path uses the configured
serverUrl it already tests for the same purpose.
Follow-up: resume was still broken. After creating a session without a
directory, the adopted session's server-side directory never matched the
local Windows path, so the fork path reintroduced the same Invalid path
failure. For remote (external non-loopback) sessions the cwd check and fork
are now skipped entirely — any adopted session is reused in place.
isLoopbackBaseUrl is exported for the adapter to share the same heuristic.
Three of the five new tests cover the cases that must NOT change, and they
pass against the previous always-send behaviour as well, so they pin the
localhost case rather than the fix.
Fixespingdotgg#3094
@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 59b7548 to 28715a9CompareAugust 30, 2026 09:52
: {}),
throwOnError: true,
});
createOpencodeClient(buildOpenCodeSdkClientConfig(input));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:638

createOpenCodeSdkClient sends directory to external OpenCode servers because the external-server path in connectToOpenCodeServer does not set external: true. As a result, buildOpenCodeSdkClientConfig keeps sendDirectory true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass external: true when creating the client for the external-server branch.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 638:
`createOpenCodeSdkClient` sends `directory` to external OpenCode servers because the external-server path in `connectToOpenCodeServer` does not set `external: true`. As a result, `buildOpenCodeSdkClientConfig` keeps `sendDirectory` true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass `external: true` when creating the client for the external-server branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Connecting to a remote OpenCode server through URL running on Linux from a Windows machine does not work

1 participant

@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(server): stop sending the local directory to a remote OpenCode server - #6228

Open
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory
Open

fix(server): stop sending the local directory to a remote OpenCode server#6228
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory

Conversation

@CDVolvik

@CDVolvikCDVolvik commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What Changed

createOpenCodeSdkClient no longer forwards the local directory to an OpenCode server that is both external and not on loopback. The client config moved into a pure buildOpenCodeSdkClientConfig so the decision is testable on its own, and the three callers pass the externality they already hold.

Why

Fixes#3094. All three call sites pass a local path unconditionally, so a Linux OpenCode server joins a Windows path onto its own and produces Invalid path /var/log/C:\Users\xxx. The error text comes from OpenCode's own bundle; what this repo controls is handing it a path that cannot mean anything on that host.

The obvious version of this fix — drop directory whenever server.external — is wrong, which is why the diff is a little larger than one line. Someone running OpenCode locally and pointing t3code at http://localhost:4096 is also external: true, and there the local directory is correct and useful. Dropping it would move those users to the server's own cwd and trade a loud bug for a quiet one. So localhost, 127.0.0.0/8, ::1, 0.0.0.0 and an unparseable base URL all keep the directory; a malformed setting cannot quietly change what the server receives.

The loopback narrowing is a heuristic and it is the one thing here I would rather you chose than me. If you would prefer an explicit setting, or a different definition of "remote", say which and I will change it.

Tests: 97/97 across the opencode and text-generation suites, tsgo --noEmit clean. Two new tests fail when the decision is reverted to always-send. Three others pass either way on purpose — they pin the local-external case, which is the regression the naive one-liner would have caused.

One honest limit: because buildOpenCodeSdkClientConfig is new, "fails without the fix" was demonstrated by reverting the decision and keeping the helper. Deleting the helper outright would only prove its own absence.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (none; server-side only)
  • I included a video for animation/interaction changes (none; server-side only)

Note

Medium Risk
Changes OpenCode connection and session-resume behavior for remote servers; loopback external URLs are explicitly preserved, but misclassified hostnames could still omit or send directory incorrectly.

Overview
Fixes #3094 by stopping the server from forwarding the client’s local directory to OpenCode when the target is an external, non-loopback host, which was producing invalid joined paths (e.g. Linux server + Windows cwd).

SDK client setup is centralized in buildOpenCodeSdkClientConfig with isLoopbackBaseUrl: directory is omitted only when external is true and the base URL is not localhost/127.x/::1 (unparseable URLs still send directory so misconfiguration does not silently drop it). Adapter, provider inventory, and text-generation paths pass external into createOpenCodeSdkClient.

Session resume in OpenCodeAdapter treats the same “remote” case as reusable without cwd comparison or session.fork, so resume no longer forks with a local path when the adopted session’s directory is server-side only. Local/managed behavior is unchanged.

Reviewed by Cursor Bugbot for commit 28715a9. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Stop sending local directory to remote OpenCode servers

  • Adds isLoopbackBaseUrl and buildOpenCodeSdkClientConfig in opencodeRuntime.ts so the SDK client omits the directory field for external, non-loopback servers while still sending auth headers
  • Updates startSession in OpenCodeAdapter.ts to treat adopted sessions from remote servers as reusable without comparing directories and to skip forking, only calling session.update to reassert permissions
  • Passes the external flag through all SDK client construction sites: inventory loading in OpenCodeProvider.ts and text generation in OpenCodeTextGeneration.ts
  • Behavioral Change: local directory is no longer included in SDK client config for remote servers; remote sessions are always reused rather than forked when a directory mismatch occurs

Macroscope summarized 28715a9.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ca0bfb4-e3dc-4cab-831c-3784097226fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Your free Security trial is over. An organization admin can activate Security or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 11, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 45e3645. Configure here.

Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — The PR is a focused OpenCode server bug fix with bounded runtime changes and targeted tests, preserving existing managed and loopback behavior. Open High-severity findings still identify risks in external client propagation and loopback classification, which independently require resolution under repository policy.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 45e3645 to f7cdd88CompareAugust 28, 2026 15:47
@CDVolvik

Copy link
Copy Markdown
ContributorAuthor

Fixed the resume gap flagged by Cursor Bugbot @ 45e3645.

What was still broken: After creating a remote session without \directory, the adopted session's server-side Linux path (e.g. /var/log) never equalled the local Windows \C:\Users...\ — so \sameDirectory\ returned false, resume took the fork path and re-sent the Windows directory via \session.fork, reproducing the same \Invalid path\ this PR was meant to fix.

Fix in f7cdd88:

  • Exported \isLoopbackBaseUrl\ from \opencodeRuntime.ts\ (same heuristic as \�uildOpenCodeSdkClientConfig) and imported it in \OpenCodeAdapter.ts.
  • For \server.external && !isLoopbackBaseUrl(server.url)\ (true remote) any adopted session is now treated as reusable without a cwd check, and the \session.fork\ branch is gated on !isRemote.
  • Rebased onto \upstream/main\ @ \

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 28, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review: one finding — the new remote-server branch in OpenCodeAdapter.startSession changes backend behavior but has no focused test. Client-config changes in opencodeRuntime.ts are covered by the new opencodeRuntime.sdkClient.test.ts.

Posted via Macroscope — Effect Service Conventions

Comment on lines +1272 to +1277
// For a remote server the local directory is meaningless — the
// client no longer sends it (#3094) and the adopted session's
// directory is a Linux path that will never equal the Windows
// one. Skip the cwd check and the fork entirely in that case
// so we don't reintroduce the Invalid path failure this PR fixes.
const isRemote = server.external && !isLoopbackBaseUrl(server.url);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes resume behavior for a remote server (skip the cwd comparison, never fork), but nothing exercises it: the existing suite configures serverUrl: "http://127.0.0.1:9999", which is loopback, so isRemote is always false and the new branch is never taken. Since this is a backend behavior change, consider adding a focused case in OpenCodeAdapter.test.ts with a non-loopback serverUrl (the runtime mock already returns external: Boolean(serverUrl)), asserting the adopted session is reused with forkCalls empty even when its directory differs.

Posted via Macroscope — Effect Service Conventions

normalized === "localhost" ||
normalized === "::1" ||
normalized === "0.0.0.0" ||
normalized.startsWith("127.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:209

isLoopbackBaseUrl misclassifies valid local endpoints such as localhost., name.localhost, and IPv4-mapped loopback [::ffff:127.0.0.1] as remote, so buildOpenCodeSdkClientConfig omits directory for them. It also classifies remote DNS names such as 127.example.com as loopback because of the textual 127. prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary 127.* DNS names as literals.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 209:
`isLoopbackBaseUrl` misclassifies valid local endpoints such as `localhost.`, `name.localhost`, and IPv4-mapped loopback `[::ffff:127.0.0.1]` as remote, so `buildOpenCodeSdkClientConfig` omits `directory` for them. It also classifies remote DNS names such as `127.example.com` as loopback because of the textual `127.` prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary `127.*` DNS names as literals.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from f7cdd88 to 59b7548CompareAugust 28, 2026 15:59
…rver
Connecting to an OpenCode server by URL from Windows failed to load models,
with the server reporting Invalid path /var/log/C:\Users\.... The client is
built with the local working directory and forwards it to whichever server is
on the other end, so a Windows path reached a Linux host and was joined onto
its own. The message comes from OpenCode itself; what we contribute is a path
that cannot mean anything there.
Only skip the directory when the server is externally configured AND its URL
is not loopback. External is not the same thing as remote: running OpenCode
locally and pointing the setting at http://localhost:4096 is also external,
and there the directory is correct and worth sending. Dropping it for those
users would trade a visible failure for a silent one, so localhost, 127.0.0.0/8,
::1 and 0.0.0.0 all keep it, as does a base URL that cannot be parsed.
The client config moves into a pure buildOpenCodeSdkClientConfig so the
decision is testable on its own, alongside the other exported helpers in this
module. Callers pass the externality they already know: the two adapter paths
forward server.external, which OpenCodeAdapter already branches on for the
authorization header, and the text-generation path uses the configured
serverUrl it already tests for the same purpose.
Follow-up: resume was still broken. After creating a session without a
directory, the adopted session's server-side directory never matched the
local Windows path, so the fork path reintroduced the same Invalid path
failure. For remote (external non-loopback) sessions the cwd check and fork
are now skipped entirely — any adopted session is reused in place.
isLoopbackBaseUrl is exported for the adapter to share the same heuristic.
Three of the five new tests cover the cases that must NOT change, and they
pass against the previous always-send behaviour as well, so they pin the
localhost case rather than the fix.
Fixespingdotgg#3094
@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 59b7548 to 28715a9CompareAugust 30, 2026 09:52
: {}),
throwOnError: true,
});
createOpencodeClient(buildOpenCodeSdkClientConfig(input));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:638

createOpenCodeSdkClient sends directory to external OpenCode servers because the external-server path in connectToOpenCodeServer does not set external: true. As a result, buildOpenCodeSdkClientConfig keeps sendDirectory true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass external: true when creating the client for the external-server branch.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 638:
`createOpenCodeSdkClient` sends `directory` to external OpenCode servers because the external-server path in `connectToOpenCodeServer` does not set `external: true`. As a result, `buildOpenCodeSdkClientConfig` keeps `sendDirectory` true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass `external: true` when creating the client for the external-server branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Connecting to a remote OpenCode server through URL running on Linux from a Windows machine does not work

1 participant

@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(server): stop sending the local directory to a remote OpenCode server - #6228

Open
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory
Open

fix(server): stop sending the local directory to a remote OpenCode server#6228
CDVolvik wants to merge 1 commit into
pingdotgg:mainfrom
CDVolvik:fix/opencode-remote-directory

Conversation

@CDVolvik

@CDVolvikCDVolvik commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What Changed

createOpenCodeSdkClient no longer forwards the local directory to an OpenCode server that is both external and not on loopback. The client config moved into a pure buildOpenCodeSdkClientConfig so the decision is testable on its own, and the three callers pass the externality they already hold.

Why

Fixes#3094. All three call sites pass a local path unconditionally, so a Linux OpenCode server joins a Windows path onto its own and produces Invalid path /var/log/C:\Users\xxx. The error text comes from OpenCode's own bundle; what this repo controls is handing it a path that cannot mean anything on that host.

The obvious version of this fix — drop directory whenever server.external — is wrong, which is why the diff is a little larger than one line. Someone running OpenCode locally and pointing t3code at http://localhost:4096 is also external: true, and there the local directory is correct and useful. Dropping it would move those users to the server's own cwd and trade a loud bug for a quiet one. So localhost, 127.0.0.0/8, ::1, 0.0.0.0 and an unparseable base URL all keep the directory; a malformed setting cannot quietly change what the server receives.

The loopback narrowing is a heuristic and it is the one thing here I would rather you chose than me. If you would prefer an explicit setting, or a different definition of "remote", say which and I will change it.

Tests: 97/97 across the opencode and text-generation suites, tsgo --noEmit clean. Two new tests fail when the decision is reverted to always-send. Three others pass either way on purpose — they pin the local-external case, which is the regression the naive one-liner would have caused.

One honest limit: because buildOpenCodeSdkClientConfig is new, "fails without the fix" was demonstrated by reverting the decision and keeping the helper. Deleting the helper outright would only prove its own absence.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (none; server-side only)
  • I included a video for animation/interaction changes (none; server-side only)

Note

Medium Risk
Changes OpenCode connection and session-resume behavior for remote servers; loopback external URLs are explicitly preserved, but misclassified hostnames could still omit or send directory incorrectly.

Overview
Fixes #3094 by stopping the server from forwarding the client’s local directory to OpenCode when the target is an external, non-loopback host, which was producing invalid joined paths (e.g. Linux server + Windows cwd).

SDK client setup is centralized in buildOpenCodeSdkClientConfig with isLoopbackBaseUrl: directory is omitted only when external is true and the base URL is not localhost/127.x/::1 (unparseable URLs still send directory so misconfiguration does not silently drop it). Adapter, provider inventory, and text-generation paths pass external into createOpenCodeSdkClient.

Session resume in OpenCodeAdapter treats the same “remote” case as reusable without cwd comparison or session.fork, so resume no longer forks with a local path when the adopted session’s directory is server-side only. Local/managed behavior is unchanged.

Reviewed by Cursor Bugbot for commit 28715a9. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Stop sending local directory to remote OpenCode servers

  • Adds isLoopbackBaseUrl and buildOpenCodeSdkClientConfig in opencodeRuntime.ts so the SDK client omits the directory field for external, non-loopback servers while still sending auth headers
  • Updates startSession in OpenCodeAdapter.ts to treat adopted sessions from remote servers as reusable without comparing directories and to skip forking, only calling session.update to reassert permissions
  • Passes the external flag through all SDK client construction sites: inventory loading in OpenCodeProvider.ts and text generation in OpenCodeTextGeneration.ts
  • Behavioral Change: local directory is no longer included in SDK client config for remote servers; remote sessions are always reused rather than forked when a directory mismatch occurs

Macroscope summarized 28715a9.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ca0bfb4-e3dc-4cab-831c-3784097226fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Your free Security trial is over. An organization admin can activate Security or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 11, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 45e3645. Configure here.

Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — The PR is a focused OpenCode server bug fix with bounded runtime changes and targeted tests, preserving existing managed and loopback behavior. Open High-severity findings still identify risks in external client propagation and loopback classification, which independently require resolution under repository policy.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 45e3645 to f7cdd88CompareAugust 28, 2026 15:47
@CDVolvik

Copy link
Copy Markdown
ContributorAuthor

Fixed the resume gap flagged by Cursor Bugbot @ 45e3645.

What was still broken: After creating a remote session without \directory, the adopted session's server-side Linux path (e.g. /var/log) never equalled the local Windows \C:\Users...\ — so \sameDirectory\ returned false, resume took the fork path and re-sent the Windows directory via \session.fork, reproducing the same \Invalid path\ this PR was meant to fix.

Fix in f7cdd88:

  • Exported \isLoopbackBaseUrl\ from \opencodeRuntime.ts\ (same heuristic as \�uildOpenCodeSdkClientConfig) and imported it in \OpenCodeAdapter.ts.
  • For \server.external && !isLoopbackBaseUrl(server.url)\ (true remote) any adopted session is now treated as reusable without a cwd check, and the \session.fork\ branch is gated on !isRemote.
  • Rebased onto \upstream/main\ @ \

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 28, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review: one finding — the new remote-server branch in OpenCodeAdapter.startSession changes backend behavior but has no focused test. Client-config changes in opencodeRuntime.ts are covered by the new opencodeRuntime.sdkClient.test.ts.

Posted via Macroscope — Effect Service Conventions

Comment on lines +1272 to +1277
// For a remote server the local directory is meaningless — the
// client no longer sends it (#3094) and the adopted session's
// directory is a Linux path that will never equal the Windows
// one. Skip the cwd check and the fork entirely in that case
// so we don't reintroduce the Invalid path failure this PR fixes.
const isRemote = server.external && !isLoopbackBaseUrl(server.url);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes resume behavior for a remote server (skip the cwd comparison, never fork), but nothing exercises it: the existing suite configures serverUrl: "http://127.0.0.1:9999", which is loopback, so isRemote is always false and the new branch is never taken. Since this is a backend behavior change, consider adding a focused case in OpenCodeAdapter.test.ts with a non-loopback serverUrl (the runtime mock already returns external: Boolean(serverUrl)), asserting the adopted session is reused with forkCalls empty even when its directory differs.

Posted via Macroscope — Effect Service Conventions

normalized === "localhost" ||
normalized === "::1" ||
normalized === "0.0.0.0" ||
normalized.startsWith("127.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:209

isLoopbackBaseUrl misclassifies valid local endpoints such as localhost., name.localhost, and IPv4-mapped loopback [::ffff:127.0.0.1] as remote, so buildOpenCodeSdkClientConfig omits directory for them. It also classifies remote DNS names such as 127.example.com as loopback because of the textual 127. prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary 127.* DNS names as literals.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 209:
`isLoopbackBaseUrl` misclassifies valid local endpoints such as `localhost.`, `name.localhost`, and IPv4-mapped loopback `[::ffff:127.0.0.1]` as remote, so `buildOpenCodeSdkClientConfig` omits `directory` for them. It also classifies remote DNS names such as `127.example.com` as loopback because of the textual `127.` prefix, causing the local directory to be sent to external servers. Use proper hostname/IP parsing to recognize loopback domains and IPv4/IPv6 loopback addresses without treating arbitrary `127.*` DNS names as literals.

@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from f7cdd88 to 59b7548CompareAugust 28, 2026 15:59
…rver
Connecting to an OpenCode server by URL from Windows failed to load models,
with the server reporting Invalid path /var/log/C:\Users\.... The client is
built with the local working directory and forwards it to whichever server is
on the other end, so a Windows path reached a Linux host and was joined onto
its own. The message comes from OpenCode itself; what we contribute is a path
that cannot mean anything there.
Only skip the directory when the server is externally configured AND its URL
is not loopback. External is not the same thing as remote: running OpenCode
locally and pointing the setting at http://localhost:4096 is also external,
and there the directory is correct and worth sending. Dropping it for those
users would trade a visible failure for a silent one, so localhost, 127.0.0.0/8,
::1 and 0.0.0.0 all keep it, as does a base URL that cannot be parsed.
The client config moves into a pure buildOpenCodeSdkClientConfig so the
decision is testable on its own, alongside the other exported helpers in this
module. Callers pass the externality they already know: the two adapter paths
forward server.external, which OpenCodeAdapter already branches on for the
authorization header, and the text-generation path uses the configured
serverUrl it already tests for the same purpose.
Follow-up: resume was still broken. After creating a session without a
directory, the adopted session's server-side directory never matched the
local Windows path, so the fork path reintroduced the same Invalid path
failure. For remote (external non-loopback) sessions the cwd check and fork
are now skipped entirely — any adopted session is reused in place.
isLoopbackBaseUrl is exported for the adapter to share the same heuristic.
Three of the five new tests cover the cases that must NOT change, and they
pass against the previous always-send behaviour as well, so they pin the
localhost case rather than the fix.
Fixespingdotgg#3094
@CDVolvik
CDVolvikforce-pushed the fix/opencode-remote-directory branch from 59b7548 to 28715a9CompareAugust 30, 2026 09:52
: {}),
throwOnError: true,
});
createOpencodeClient(buildOpenCodeSdkClientConfig(input));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Highprovider/opencodeRuntime.ts:638

createOpenCodeSdkClient sends directory to external OpenCode servers because the external-server path in connectToOpenCodeServer does not set external: true. As a result, buildOpenCodeSdkClientConfig keeps sendDirectory true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass external: true when creating the client for the external-server branch.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/opencodeRuntime.ts around line 638:
`createOpenCodeSdkClient` sends `directory` to external OpenCode servers because the external-server path in `connectToOpenCodeServer` does not set `external: true`. As a result, `buildOpenCodeSdkClientConfig` keeps `sendDirectory` true and remote servers receive the caller's local path, which can cause invalid-path errors. Pass `external: true` when creating the client for the external-server branch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Connecting to a remote OpenCode server through URL running on Linux from a Windows machine does not work

1 participant

@CDVolvik