authorgravatar for jono@foodnotblogs.comJono <jono@foodnotblogs.com> 2026-08-15 05:27:58-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-15 14:27:58+02:00
log61b2e744df378b7a8d534494114cf59b26cbe6ca
treeac45286c8981916ac0c1924f572dadee922c8553
parente17f244e0d411422dacaa0a43669fb4e8436347d
signature Signed by PGP key B5690EEEBB952194

fix(server): respect inherited OPENCODE_CONFIG_CONTENT (#4242)

Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com>

2 files changed, 42 insertions(+), 1 deletions(-)

apps/server/src/provider/opencodeRuntime.environment.test.ts created+23
......@@ -0,0 +1,23 @@
1import { describe, expect, it } from "vite-plus/test";
2
3import { resolveOpenCodeConfigContent } from "./opencodeRuntime.ts";
4
5describe("resolveOpenCodeConfigContent", () => {
6 it("prefers the caller environment over the inherited environment", () => {
7 expect(
8 resolveOpenCodeConfigContent(
9 { OPENCODE_CONFIG_CONTENT: '{"source":"caller"}' },
10 { OPENCODE_CONFIG_CONTENT: '{"source":"process"}' },
11 ),
12 ).toBe('{"source":"caller"}');
13 });
14
15 it("falls back to the inherited environment and then an empty config", () => {
16 expect(
17 resolveOpenCodeConfigContent(undefined, {
18 OPENCODE_CONFIG_CONTENT: '{"source":"process"}',
19 }),
20 ).toBe('{"source":"process"}');
21 expect(resolveOpenCodeConfigContent(undefined, {})).toBe("{}");
22 });
23});
apps/server/src/provider/opencodeRuntime.ts+19-1
......@@ -37,6 +37,17 @@ import { resolveSpawnCommand } from "@t3tools/shared/shell";
3737const encodeUnknownJsonStringExit = Schema.encodeUnknownExit(Schema.fromJsonString(Schema.Unknown));
3838const OPENCODE_EMPTY_CONFIG_CONTENT = "{}";
3939
40export function resolveOpenCodeConfigContent(
41 inputEnvironment: Readonly<Record<string, string | undefined>> | undefined,
42 inheritedEnvironment: Readonly<Record<string, string | undefined>> = process.env,
43): string {
44 return (
45 inputEnvironment?.OPENCODE_CONFIG_CONTENT ??
46 inheritedEnvironment.OPENCODE_CONFIG_CONTENT ??
47 OPENCODE_EMPTY_CONFIG_CONTENT
48 );
49}
50
4051const OPENCODE_SERVER_READY_PREFIX = "opencode server listening";
4152const DEFAULT_OPENCODE_SERVER_TIMEOUT_MS = 30_000;
4253const DEFAULT_HOSTNAME = "127.0.0.1";
......@@ -467,7 +478,14 @@ const makeOpenCodeRuntime = Effect.gen(function* () {
467478 shell: spawnCommand.shell,
468479 env: {
469480 ...input.environment,
470 OPENCODE_CONFIG_CONTENT: OPENCODE_EMPTY_CONFIG_CONTENT,
481 // Respect an OPENCODE_CONFIG_CONTENT provided by the caller or
482 // the inherited process environment, only falling back to the
483 // empty config when neither is set. Setting it unconditionally
484 // previously clobbered the user's opencode config, hiding their
485 // providers/models. The value is set explicitly (rather than
486 // relying on inheritance) because `extendEnv` is false whenever
487 // `input.environment` is provided.
488 OPENCODE_CONFIG_CONTENT: resolveOpenCodeConfigContent(input.environment),
471489 },
472490 extendEnv: input.environment === undefined,
473491 }),