fix(server): keep env-provided OPENCODE_BINARY when settings clear the override

This commit is contained in:
bashrusakh
2026-08-19 10:38:53 +11:00
parent ef2afdc759
commit 3feacad69b
3 changed files with 41 additions and 1 deletions
+1
View File
@@ -30,6 +30,7 @@ All notable changes to this project will be documented in this file.
- Desktop: browser pages served from a self-signed loopback HTTPS address now load instead of being blocked by the certificate warning. - Desktop: browser pages served from a self-signed loopback HTTPS address now load instead of being blocked by the certificate warning.
- Browser: typing a comment on a page no longer triggers app shortcuts. - Browser: typing a comment on a page no longer triggers app shortcuts.
- Skills Catalog: the source is now named ClawHub instead of "ClawdHub" (thanks to @makeittech). - Skills Catalog: the source is now named ClawHub instead of "ClawdHub" (thanks to @makeittech).
- Settings: an explicitly set `OPENCODE_BINARY` environment variable is no longer discarded when settings contain an empty opencodeBinary value; the environment variable keeps pointing the managed OpenCode server at the binary you chose.
## [1.18.4] - 2026-08-14 ## [1.18.4] - 2026-08-14
@@ -1011,7 +1011,13 @@ export const createOpenCodeEnvRuntime = (deps) => {
const normalized = normalizeOpencodeBinarySetting(settings.opencodeBinary); const normalized = normalizeOpencodeBinarySetting(settings.opencodeBinary);
if (normalized === '') { if (normalized === '') {
delete process.env.OPENCODE_BINARY; // The empty-string sentinel drops a previously APPLIED settings
// override (source === 'settings'). An OPENCODE_BINARY provided by
// the user's own environment is explicit configuration and must not
// be destroyed by an empty setting.
if (state.resolvedOpencodeBinarySource === 'settings') {
delete process.env.OPENCODE_BINARY;
}
state.resolvedOpencodeBinary = null; state.resolvedOpencodeBinary = null;
state.resolvedOpencodeBinarySource = null; state.resolvedOpencodeBinarySource = null;
clearWslOpencodeResolution(); clearWslOpencodeResolution();
@@ -200,6 +200,39 @@ describe('OpenCode env runtime', () => {
expect(state.resolvedOpencodeBinarySource).toBe('settings'); expect(state.resolvedOpencodeBinarySource).toBe('settings');
}); });
it('keeps an env-provided OPENCODE_BINARY when the setting is an empty-string sentinel', async () => {
const dir = createTempDir('openchamber-env-opencode-');
const binary = path.join(dir, 'opencode');
fs.writeFileSync(binary, '#!/bin/sh\nexit 0\n');
if (process.platform !== 'win32') fs.chmodSync(binary, 0o755);
process.env.OPENCODE_BINARY = binary;
const { runtime, state } = createRuntime({ opencodeBinary: '' });
await expect(runtime.applyOpencodeBinaryFromSettings()).resolves.toBeNull();
expect(process.env.OPENCODE_BINARY).toBe(binary);
expect(state.resolvedOpencodeBinary).toBeNull();
expect(state.resolvedOpencodeBinarySource).toBeNull();
});
it('drops a previously applied settings override when the setting is cleared to an empty string', async () => {
const dir = createTempDir('openchamber-settings-opencode-');
const binary = path.join(dir, 'opencode');
fs.writeFileSync(binary, '#!/bin/sh\nexit 0\n');
if (process.platform !== 'win32') fs.chmodSync(binary, 0o755);
const settings = { opencodeBinary: binary };
const { runtime, state } = createRuntime(settings);
await expect(runtime.applyOpencodeBinaryFromSettings()).resolves.toBe(binary);
expect(process.env.OPENCODE_BINARY).toBe(binary);
expect(state.resolvedOpencodeBinarySource).toBe('settings');
settings.opencodeBinary = '';
await expect(runtime.applyOpencodeBinaryFromSettings()).resolves.toBeNull();
expect(process.env.OPENCODE_BINARY).toBeUndefined();
expect(state.resolvedOpencodeBinary).toBeNull();
expect(state.resolvedOpencodeBinarySource).toBeNull();
});
it('prefers the bundled CLI over a user-installed OpenCode from PATH', () => { it('prefers the bundled CLI over a user-installed OpenCode from PATH', () => {
const bundledDir = createTempDir('openchamber-bundled-opencode-'); const bundledDir = createTempDir('openchamber-bundled-opencode-');
const bundledBinary = path.join(bundledDir, process.platform === 'win32' ? 'opencode.exe' : 'opencode'); const bundledBinary = path.join(bundledDir, process.platform === 'win32' ? 'opencode.exe' : 'opencode');