authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-26 19:23:26-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-02-26 19:27:08-08:00
log9c4095aaaa31c5628d40026cbddf094c0f85146d
treefb5dcc2d84b2da9f247308cbdc804ecbe954aedb
parent961df8597c4c8149febbc95d0ab52f895ca7ff94

Fix Effect type warnings to pass typecheck

- Use generic type parameter for stream errors instead of unknown - Type ServerShape errors as ServerLifecycleError instead of unknown - Add error mapping for autoBootstrapProject and httpServerListen - Type makeServerProviderLayer with ProviderUnsupportedError - Use Effect.try with decodeUnknownSync in projector to avoid unknown requirements - Fix test layer types from any/unknown to never Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

6 files changed, 41 insertions(+), 29 deletions(-)

apps/server/src/git/Layers/CodexTextGeneration.ts+2-2
......@@ -129,9 +129,9 @@ const makeCodexTextGeneration = Effect.gen(function* () {
129129 const path = yield* Path.Path;
130130 const commandSpawner = yield* ChildProcessSpawner.ChildProcessSpawner;
131131
132 const readStreamAsString = (
132 const readStreamAsString = <E>(
133133 operation: string,
134 stream: Stream.Stream<Uint8Array, unknown>,
134 stream: Stream.Stream<Uint8Array, E>,
135135 ): Effect.Effect<string, TextGenerationError> =>
136136 Effect.gen(function* () {
137137 let text = "";
apps/server/src/git/Layers/GitService.ts+2-2
......@@ -39,9 +39,9 @@ function toGitCommandError(
3939 });
4040}
4141
42const collectOutput = Effect.fn(function* (
42const collectOutput = Effect.fn(function* <E>(
4343 input: Pick<ExecuteGitInput, "operation" | "cwd" | "args">,
44 stream: Stream.Stream<Uint8Array, unknown>,
44 stream: Stream.Stream<Uint8Array, E>,
4545 maxOutputBytes: number,
4646): Effect.fn.Return<string, GitCommandError> {
4747 const decoder = new TextDecoder();
apps/server/src/orchestration/projector.ts+6-3
......@@ -40,9 +40,12 @@ function decodeForEvent<A>(
4040 eventType: OrchestrationEvent["type"],
4141 field: string,
4242): Effect.Effect<A, OrchestrationProjectorDecodeError> {
43 return Schema.decodeUnknownEffect(schema)(value).pipe(
44 Effect.mapError(toProjectorDecodeError(`${eventType}:${field}`)),
45 ) as Effect.Effect<A, OrchestrationProjectorDecodeError>;
43 return Effect.try({
44 // eslint-disable-next-line @typescript-eslint/no-explicit-any
45 try: () => Schema.decodeUnknownSync(schema as any)(value) as A,
46 catch: (error) =>
47 toProjectorDecodeError(`${eventType}:${field}`)(error as Schema.SchemaError),
48 });
4649}
4750
4851function retainThreadMessagesAfterRevert(
apps/server/src/serverLayers.ts+2-1
......@@ -17,6 +17,7 @@ import { ProviderCommandReactorLive } from "./orchestration/Layers/ProviderComma
1717import { OrchestrationProjectionPipelineLive } from "./orchestration/Layers/ProjectionPipeline";
1818import { OrchestrationProjectionSnapshotQueryLive } from "./orchestration/Layers/ProjectionSnapshotQuery";
1919import { ProviderRuntimeIngestionLive } from "./orchestration/Layers/ProviderRuntimeIngestion";
20import { ProviderUnsupportedError } from "./provider/Errors";
2021import { makeCodexAdapterLive } from "./provider/Layers/CodexAdapter";
2122import { ProviderAdapterRegistryLive } from "./provider/Layers/ProviderAdapterRegistry";
2223import { makeProviderServiceLive } from "./provider/Layers/ProviderService";
......@@ -35,7 +36,7 @@ import { NodePtyAdapterLive } from "./terminal/Layers/NodePTY";
3536
3637export function makeServerProviderLayer(): Layer.Layer<
3738 ProviderService,
38 unknown,
39 ProviderUnsupportedError,
3940 SqlClient.SqlClient | ServerConfig
4041> {
4142 return Effect.gen(function* () {
apps/server/src/wsServer.test.ts+2-2
......@@ -323,14 +323,14 @@ describe("WebSocket Server", () => {
323323
324324 async function createTestServer(
325325 options: {
326 persistenceLayer?: Layer.Layer<SqlClient.SqlClient, any>;
326 persistenceLayer?: Layer.Layer<SqlClient.SqlClient, never>;
327327 cwd?: string;
328328 autoBootstrapProjectFromCwd?: boolean;
329329 logWebSocketEvents?: boolean;
330330 devUrl?: string;
331331 authToken?: string;
332332 stateDir?: string;
333 providerLayer?: Layer.Layer<ProviderService, unknown>;
333 providerLayer?: Layer.Layer<ProviderService, never>;
334334 open?: OpenShape;
335335 gitManager?: GitManagerShape;
336336 gitCore?: Pick<GitCoreShape, "listBranches" | "initRepo" | "pullCurrentBranch">;
apps/server/src/wsServer.ts+27-19
......@@ -66,14 +66,14 @@ export interface ServerShape {
6666 */
6767 readonly start: Effect.Effect<
6868 http.Server,
69 unknown,
69 ServerLifecycleError,
7070 Scope.Scope | ServerRuntimeServices | ServerConfig
7171 >;
7272
7373 /**
7474 * Wait for process shutdown signals.
7575 */
76 readonly stopSignal: Effect.Effect<unknown, never>;
76 readonly stopSignal: Effect.Effect<void, never>;
7777}
7878
7979/**
......@@ -165,7 +165,7 @@ class RouteRequestError extends Schema.TaggedErrorClass<RouteRequestError>()("Ro
165165
166166export const createServer = Effect.fn(function* (): Effect.fn.Return<
167167 http.Server,
168 unknown, // TODO: This should not be unknown
168 ServerLifecycleError,
169169 Scope.Scope | ServerRuntimeServices | ServerConfig
170170> {
171171 const serverConfig = yield* ServerConfig;
......@@ -338,21 +338,27 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return<
338338 yield* Scope.provide(orchestrationReactor.start, subscriptionsScope);
339339
340340 if (autoBootstrapProjectFromCwd) {
341 const snapshot = yield* projectionReadModelQuery.getSnapshot();
342 const existing = snapshot.projects.find((project) => project.workspaceRoot === cwd);
343 if (!existing) {
344 const createdAt = new Date().toISOString();
345 const projectName = path.basename(cwd) || "project";
346 yield* orchestrationEngine.dispatch({
347 type: "project.create",
348 commandId: CommandId.makeUnsafe(crypto.randomUUID()),
349 projectId: ProjectId.makeUnsafe(crypto.randomUUID()),
350 title: projectName,
351 workspaceRoot: cwd,
352 defaultModel: "gpt-5-codex",
353 createdAt,
354 });
355 }
341 yield* Effect.gen(function* () {
342 const snapshot = yield* projectionReadModelQuery.getSnapshot();
343 const existing = snapshot.projects.find((project) => project.workspaceRoot === cwd);
344 if (!existing) {
345 const createdAt = new Date().toISOString();
346 const projectName = path.basename(cwd) || "project";
347 yield* orchestrationEngine.dispatch({
348 type: "project.create",
349 commandId: CommandId.makeUnsafe(crypto.randomUUID()),
350 projectId: ProjectId.makeUnsafe(crypto.randomUUID()),
351 title: projectName,
352 workspaceRoot: cwd,
353 defaultModel: "gpt-5-codex",
354 createdAt,
355 });
356 }
357 }).pipe(
358 Effect.mapError(
359 (cause) => new ServerLifecycleError({ operation: "autoBootstrapProject", cause }),
360 ),
361 );
356362 }
357363
358364 const routeRequest = Effect.fnUntraced(function* (request: WebSocketRequest) {
......@@ -618,7 +624,9 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return<
618624 );
619625 yield* Effect.addFinalizer(() => Effect.sync(() => unsubscribeTerminalEvents()));
620626
621 yield* NodeHttpServer.make(() => httpServer, listenOptions);
627 yield* NodeHttpServer.make(() => httpServer, listenOptions).pipe(
628 Effect.mapError((cause) => new ServerLifecycleError({ operation: "httpServerListen", cause })),
629 );
622630
623631 yield* Effect.addFinalizer(() =>
624632 Effect.all([