Skip to content

Commit 9a0838f

Browse files
committed
fix: stabilize env runtime services and panel scrolling
1 parent 13012a3 commit 9a0838f

16 files changed

Lines changed: 71 additions & 104 deletions

File tree

apps/server/integration/OrchestrationEngineHarness.integration.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { ProviderSessionRuntimeRepositoryLive } from "../src/persistence/Layers/
3535
import { makeSqlitePersistenceLive } from "../src/persistence/Layers/Sqlite.ts";
3636
import { ProjectionCheckpointRepository } from "../src/persistence/Services/ProjectionCheckpoints.ts";
3737
import { ProjectionPendingApprovalRepository } from "../src/persistence/Services/ProjectionPendingApprovals.ts";
38+
import { EnvironmentVariablesLive } from "../src/persistence/Services/EnvironmentVariables.ts";
3839
import { ProviderUnsupportedError } from "../src/provider/Errors.ts";
3940
import { ProviderAdapterRegistry } from "../src/provider/Services/ProviderAdapterRegistry.ts";
4041
import { ProviderSessionDirectoryLive } from "../src/provider/Layers/ProviderSessionDirectory.ts";
@@ -286,14 +287,15 @@ export const makeOrchestrationIntegrationHarness = (
286287
);
287288

288289
const checkpointStoreLayer = CheckpointStoreLive.pipe(Layer.provide(GitCoreLive));
289-
const runtimeServicesLayer = Layer.mergeAll(
290-
orchestrationLayer,
291-
OrchestrationProjectionSnapshotQueryLive,
292-
ProjectionCheckpointRepositoryLive,
293-
ProjectionPendingApprovalRepositoryLive,
294-
checkpointStoreLayer,
295-
providerLayer,
296-
RuntimeReceiptBusLive,
290+
const runtimeServicesLayer = Layer.empty.pipe(
291+
Layer.provideMerge(EnvironmentVariablesLive),
292+
Layer.provideMerge(OrchestrationProjectionSnapshotQueryLive),
293+
Layer.provideMerge(orchestrationLayer),
294+
Layer.provideMerge(ProjectionCheckpointRepositoryLive),
295+
Layer.provideMerge(ProjectionPendingApprovalRepositoryLive),
296+
Layer.provideMerge(checkpointStoreLayer),
297+
Layer.provideMerge(providerLayer),
298+
Layer.provideMerge(RuntimeReceiptBusLive),
297299
);
298300
const runtimeIngestionLayer = ProviderRuntimeIngestionLive.pipe(
299301
Layer.provideMerge(runtimeServicesLayer),

apps/server/src/codexAppServerManager.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
ProviderInteractionMode,
2121
} from "@okcode/contracts";
2222
import { normalizeModelSlug } from "@okcode/shared/model";
23-
import { mergeNodeProcessEnv } from "@okcode/shared/environment";
23+
import { compactNodeProcessEnv, mergeNodeProcessEnv } from "@okcode/shared/environment";
2424
import { Effect, ServiceMap } from "effect";
2525

2626
import {
@@ -574,13 +574,15 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
574574
const codexOptions = readCodexProviderOptions(input);
575575
const codexBinaryPath = codexOptions.binaryPath ?? "codex";
576576
const codexHomePath = codexOptions.homePath;
577-
const baseEnv = mergeNodeProcessEnv(process.env, input.env);
577+
const baseEnv = mergeNodeProcessEnv(
578+
process.env,
579+
input.env ? compactNodeProcessEnv(input.env) : undefined,
580+
);
578581
const sessionEnv = codexHomePath ? { ...baseEnv, CODEX_HOME: codexHomePath } : baseEnv;
579582
this.assertSupportedCodexCliVersion({
580583
binaryPath: codexBinaryPath,
581584
cwd: resolvedCwd,
582585
...(codexHomePath ? { homePath: codexHomePath } : {}),
583-
env: sessionEnv,
584586
});
585587
const child = spawn(codexBinaryPath, ["app-server"], {
586588
cwd: resolvedCwd,

apps/server/src/git/Layers/CodexTextGeneration.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { sanitizeBranchFragment, sanitizeFeatureBranchName } from "@okcode/share
99

1010
import { resolveAttachmentPath } from "../../attachmentStore.ts";
1111
import { ServerConfig } from "../../config.ts";
12-
import { ProjectionSnapshotQuery } from "../../orchestration/Services/ProjectionSnapshotQuery.ts";
1312
import { TextGenerationError } from "../Errors.ts";
1413
import {
1514
type BranchNameGenerationInput,
@@ -19,7 +18,6 @@ import {
1918
type TextGenerationShape,
2019
TextGeneration,
2120
} from "../Services/TextGeneration.ts";
22-
import { resolveRuntimeEnvironment } from "../../runtimeEnvironment.ts";
2321

2422
const CODEX_REASONING_EFFORT = "low";
2523
const CODEX_TIMEOUT_MS = 180_000;
@@ -103,7 +101,6 @@ const makeCodexTextGeneration = Effect.gen(function* () {
103101
const path = yield* Path.Path;
104102
const commandSpawner = yield* ChildProcessSpawner.ChildProcessSpawner;
105103
const serverConfig = yield* Effect.service(ServerConfig);
106-
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
107104

108105
type MaterializedImageAttachments = {
109106
readonly imagePaths: ReadonlyArray<string>;
@@ -210,10 +207,6 @@ const makeCodexTextGeneration = Effect.gen(function* () {
210207
const outputPath = yield* writeTempFile(operation, "codex-output", "");
211208

212209
const runCodexCommand = Effect.gen(function* () {
213-
const runtimeEnv = yield* resolveRuntimeEnvironment({
214-
cwd,
215-
readModel: yield* projectionSnapshotQuery.getSnapshot(),
216-
});
217210
const command = ChildProcess.make(
218211
"codex",
219212
[
@@ -235,7 +228,7 @@ const makeCodexTextGeneration = Effect.gen(function* () {
235228
{
236229
cwd,
237230
shell: process.platform === "win32",
238-
env: mergeNodeProcessEnv(process.env, runtimeEnv),
231+
env: process.env,
239232
stdin: {
240233
stream: Stream.make(new TextEncoder().encode(prompt)),
241234
},

apps/server/src/git/Layers/GitCore.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
Stream,
1818
} from "effect";
1919
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
20-
import { mergeNodeProcessEnv } from "@okcode/shared/environment";
20+
import { compactNodeProcessEnv, mergeNodeProcessEnv } from "@okcode/shared/environment";
2121

2222
import { GitCommandError } from "../Errors.ts";
2323
import {
@@ -136,7 +136,6 @@ const EMPTY_STATUS_DETAILS = {
136136
aheadCount: 0,
137137
behindCount: 0,
138138
upstreamRef: null,
139-
pr: null,
140139
} satisfies GitStatusDetails;
141140

142141
function parseBranchLine(line: string): { name: string; current: boolean } | null {
@@ -525,7 +524,6 @@ export const makeGitCore = (options?: { executeOverride?: GitCoreShape["execute"
525524
const fileSystem = yield* FileSystem.FileSystem;
526525
const path = yield* Path.Path;
527526
const { worktreesDir } = yield* ServerConfig;
528-
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
529527

530528
let execute: GitCoreShape["execute"];
531529

@@ -547,20 +545,16 @@ export const makeGitCore = (options?: { executeOverride?: GitCoreShape["execute"
547545
Effect.provideService(FileSystem.FileSystem, fileSystem),
548546
Effect.mapError(toGitCommandError(commandInput, "failed to create trace2 monitor.")),
549547
);
550-
const runtimeEnv =
551-
input.env !== undefined
552-
? input.env
553-
: yield* resolveRuntimeEnvironment({
554-
cwd: commandInput.cwd,
555-
readModel: yield* projectionSnapshotQuery.getSnapshot(),
556-
});
548+
const runtimeEnv = input.env ? compactNodeProcessEnv(input.env) : undefined;
557549
const child = yield* commandSpawner
558550
.spawn(
559551
ChildProcess.make("git", commandInput.args, {
560552
cwd: commandInput.cwd,
561553
env: mergeNodeProcessEnv(
562-
mergeNodeProcessEnv(process.env, runtimeEnv),
563-
trace2Monitor.env,
554+
compactNodeProcessEnv(
555+
mergeNodeProcessEnv(compactNodeProcessEnv(process.env), runtimeEnv),
556+
),
557+
compactNodeProcessEnv(trace2Monitor.env),
564558
),
565559
}),
566560
)

apps/server/src/git/Layers/GitHubCli.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,21 +170,14 @@ function decodeGitHubJson<S extends Schema.Top>(
170170

171171
const makeGitHubCli = Effect.sync(() => {
172172
const execute: GitHubCliShape["execute"] = (input) =>
173-
Effect.gen(function* () {
174-
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
175-
const runtimeEnv = yield* resolveRuntimeEnvironment({
176-
cwd: input.cwd,
177-
readModel: yield* projectionSnapshotQuery.getSnapshot(),
178-
});
179-
return yield* Effect.tryPromise({
180-
try: () =>
181-
runProcess("gh", input.args, {
182-
cwd: input.cwd,
183-
timeoutMs: input.timeoutMs ?? DEFAULT_TIMEOUT_MS,
184-
env: mergeNodeProcessEnv(process.env, runtimeEnv),
185-
}),
186-
catch: (error) => normalizeGitHubCliError("execute", error),
187-
});
173+
Effect.tryPromise({
174+
try: () =>
175+
runProcess("gh", input.args, {
176+
cwd: input.cwd,
177+
timeoutMs: input.timeoutMs ?? DEFAULT_TIMEOUT_MS,
178+
env: process.env,
179+
}),
180+
catch: (error) => normalizeGitHubCliError("execute", error),
188181
});
189182

190183
const service = {

apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { ProviderAdapterRequestError } from "../../provider/Errors.ts";
2222
import { OrchestrationEventStoreLive } from "../../persistence/Layers/OrchestrationEventStore.ts";
2323
import { OrchestrationCommandReceiptRepositoryLive } from "../../persistence/Layers/OrchestrationCommandReceipts.ts";
2424
import { SqlitePersistenceMemory } from "../../persistence/Layers/Sqlite.ts";
25+
import { EnvironmentVariablesLive } from "../../persistence/Services/EnvironmentVariables.ts";
2526
import {
2627
ProviderService,
2728
type ProviderServiceShape,
@@ -219,12 +220,14 @@ describe("ProviderCommandReactor", () => {
219220
);
220221
const layer = ProviderCommandReactorLive.pipe(
221222
Layer.provideMerge(orchestrationLayer),
223+
Layer.provideMerge(EnvironmentVariablesLive),
222224
Layer.provideMerge(Layer.succeed(ProviderService, service)),
223225
Layer.provideMerge(Layer.succeed(GitCore, { renameBranch } as unknown as GitCoreShape)),
224226
Layer.provideMerge(
225227
Layer.succeed(TextGeneration, { generateBranchName } as unknown as TextGenerationShape),
226228
),
227229
Layer.provideMerge(ServerConfig.layerTest(process.cwd(), baseDir)),
230+
Layer.provideMerge(SqlitePersistenceMemory),
228231
Layer.provideMerge(NodeServices.layer),
229232
);
230233
const runtime = ManagedRuntime.make(layer);

apps/server/src/persistence/Services/EnvironmentVariables.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import path from "node:path";
1414
import {
1515
type EnvironmentVariableEntry,
1616
type GlobalEnvironmentVariablesResult,
17-
type ProjectEnvironmentVariablesInput,
17+
ProjectEnvironmentVariablesInput,
1818
type ProjectEnvironmentVariablesResult,
19-
type SaveGlobalEnvironmentVariablesInput,
20-
type SaveProjectEnvironmentVariablesInput,
19+
SaveGlobalEnvironmentVariablesInput,
20+
SaveProjectEnvironmentVariablesInput,
2121
} from "@okcode/contracts";
2222
import * as SqlClient from "effect/unstable/sql/SqlClient";
2323
import * as SqlSchema from "effect/unstable/sql/SqlSchema";

apps/server/src/provider/Layers/ClaudeAdapter.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import {
4848
supportsClaudeThinkingToggle,
4949
supportsClaudeUltrathinkKeyword,
5050
} from "@okcode/shared/model";
51-
import { mergeNodeProcessEnv } from "@okcode/shared/environment";
51+
import { compactNodeProcessEnv, mergeNodeProcessEnv } from "@okcode/shared/environment";
5252
import {
5353
Cause,
5454
DateTime,
@@ -66,7 +66,6 @@ import {
6666

6767
import { resolveAttachmentPath } from "../../attachmentStore.ts";
6868
import { ServerConfig } from "../../config.ts";
69-
import { ProjectionSnapshotQuery } from "../../orchestration/Services/ProjectionSnapshotQuery.ts";
7069
import {
7170
ProviderAdapterProcessError,
7271
ProviderAdapterRequestError,
@@ -77,7 +76,6 @@ import {
7776
} from "../Errors.ts";
7877
import { ClaudeAdapter, type ClaudeAdapterShape } from "../Services/ClaudeAdapter.ts";
7978
import { type EventNdjsonLogger, makeEventNdjsonLogger } from "./EventNdjsonLogger.ts";
80-
import { resolveRuntimeEnvironment } from "../../runtimeEnvironment.ts";
8179

8280
const PROVIDER = "claudeAgent" as const;
8381
type ClaudeTextStreamKind = Extract<RuntimeContentStreamKind, "assistant_text" | "reasoning_text">;
@@ -920,7 +918,6 @@ function makeClaudeAdapter(options?: ClaudeAdapterLiveOptions) {
920918
return Effect.gen(function* () {
921919
const fileSystem = yield* FileSystem.FileSystem;
922920
const serverConfig = yield* ServerConfig;
923-
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
924921
const nativeEventLogger =
925922
options?.nativeEventLogger ??
926923
(options?.nativeEventLogPath !== undefined
@@ -2726,15 +2723,7 @@ function makeClaudeAdapter(options?: ClaudeAdapterLiveOptions) {
27262723
...(typeof thinking === "boolean" ? { alwaysThinkingEnabled: thinking } : {}),
27272724
...(fastMode ? { fastMode: true } : {}),
27282725
};
2729-
const runtimeEnv =
2730-
input.env !== undefined
2731-
? input.env
2732-
: input.cwd !== undefined
2733-
? yield* resolveRuntimeEnvironment({
2734-
cwd: input.cwd,
2735-
readModel: yield* projectionSnapshotQuery.getSnapshot(),
2736-
})
2737-
: undefined;
2726+
const runtimeEnv = input.env ? compactNodeProcessEnv(input.env) : undefined;
27382727

27392728
const queryOptions: ClaudeQueryOptions = {
27402729
...(input.cwd ? { cwd: input.cwd } : {}),

apps/server/src/provider/Layers/CodexAdapter.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
ThreadId,
2222
TurnId,
2323
} from "@okcode/contracts";
24+
import { compactNodeProcessEnv } from "@okcode/shared/environment";
2425
import { Effect, FileSystem, Layer, Queue, Schema, ServiceMap, Stream } from "effect";
2526

2627
import {
@@ -38,9 +39,7 @@ import {
3839
} from "../../codexAppServerManager.ts";
3940
import { resolveAttachmentPath } from "../../attachmentStore.ts";
4041
import { ServerConfig } from "../../config.ts";
41-
import { ProjectionSnapshotQuery } from "../../orchestration/Services/ProjectionSnapshotQuery.ts";
4242
import { type EventNdjsonLogger, makeEventNdjsonLogger } from "./EventNdjsonLogger.ts";
43-
import { resolveRuntimeEnvironment } from "../../runtimeEnvironment.ts";
4443

4544
const PROVIDER = "codex" as const;
4645

@@ -1319,7 +1318,6 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) =>
13191318
Effect.gen(function* () {
13201319
const fileSystem = yield* FileSystem.FileSystem;
13211320
const serverConfig = yield* Effect.service(ServerConfig);
1322-
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
13231321
const nativeEventLogger =
13241322
options?.nativeEventLogger ??
13251323
(options?.nativeEventLogPath !== undefined
@@ -1355,15 +1353,7 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) =>
13551353
});
13561354
}
13571355

1358-
const runtimeEnv =
1359-
input.env !== undefined
1360-
? input.env
1361-
: input.cwd !== undefined
1362-
? yield* resolveRuntimeEnvironment({
1363-
cwd: input.cwd,
1364-
readModel: yield* projectionSnapshotQuery.getSnapshot(),
1365-
})
1366-
: undefined;
1356+
const runtimeEnv = input.env ? compactNodeProcessEnv(input.env) : undefined;
13671357

13681358
const managerInput: CodexAppServerStartSessionInput = {
13691359
threadId: input.threadId,

apps/server/src/provider/Layers/ProviderHealth.ts

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import {
2323
isCodexCliVersionSupported,
2424
parseCodexCliVersion,
2525
} from "../codexCliVersion";
26-
import { EnvironmentVariables } from "../../persistence/Services/EnvironmentVariables.ts";
2726
import { ProviderHealth, type ProviderHealthShape } from "../Services/ProviderHealth";
2827

2928
const DEFAULT_TIMEOUT_MS = 4_000;
@@ -190,10 +189,7 @@ const OPENAI_AUTH_PROVIDERS = new Set(["openai"]);
190189
export const readCodexConfigModelProvider = Effect.gen(function* () {
191190
const fileSystem = yield* FileSystem.FileSystem;
192191
const path = yield* Path.Path;
193-
const environmentVariables = yield* EnvironmentVariables;
194-
const globalEnvironment = yield* environmentVariables.resolveEnvironment();
195-
const mergedEnvironment = mergeNodeProcessEnv(process.env, globalEnvironment);
196-
const codexHome = mergedEnvironment.CODEX_HOME || path.join(OS.homedir(), ".codex");
192+
const codexHome = process.env.CODEX_HOME || path.join(OS.homedir(), ".codex");
197193
const configPath = path.join(codexHome, "config.toml");
198194

199195
const content = yield* fileSystem
@@ -247,14 +243,9 @@ const collectStreamAsString = <E>(stream: Stream.Stream<Uint8Array, E>): Effect.
247243
const runCodexCommand = (args: ReadonlyArray<string>) =>
248244
Effect.gen(function* () {
249245
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
250-
const environmentVariables = yield* EnvironmentVariables;
251-
const mergedEnvironment = mergeNodeProcessEnv(
252-
process.env,
253-
yield* environmentVariables.resolveEnvironment(),
254-
);
255246
const command = ChildProcess.make("codex", [...args], {
256247
shell: process.platform === "win32",
257-
env: mergedEnvironment,
248+
env: process.env,
258249
});
259250

260251
const child = yield* spawner.spawn(command);
@@ -274,14 +265,9 @@ const runCodexCommand = (args: ReadonlyArray<string>) =>
274265
const runClaudeCommand = (args: ReadonlyArray<string>) =>
275266
Effect.gen(function* () {
276267
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
277-
const environmentVariables = yield* EnvironmentVariables;
278-
const mergedEnvironment = mergeNodeProcessEnv(
279-
process.env,
280-
yield* environmentVariables.resolveEnvironment(),
281-
);
282268
const command = ChildProcess.make("claude", [...args], {
283269
shell: process.platform === "win32",
284-
env: mergedEnvironment,
270+
env: process.env,
285271
});
286272

287273
const child = yield* spawner.spawn(command);

0 commit comments

Comments
 (0)