diff --git a/apps/server/src/git/Layers/CodexTextGeneration.ts b/apps/server/src/git/Layers/CodexTextGeneration.ts index 91b29b182a2cde292b40d93b8773c6b5c0d7d803..3fbeb1aac76e907ed102fd5451f8daa43f07ed10 100644 --- a/apps/server/src/git/Layers/CodexTextGeneration.ts +++ b/apps/server/src/git/Layers/CodexTextGeneration.ts @@ -129,9 +129,9 @@ const makeCodexTextGeneration = Effect.gen(function* () { const path = yield* Path.Path; const commandSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; - const readStreamAsString = ( + const readStreamAsString = ( operation: string, - stream: Stream.Stream, + stream: Stream.Stream, ): Effect.Effect => Effect.gen(function* () { let text = ""; diff --git a/apps/server/src/git/Layers/GitService.ts b/apps/server/src/git/Layers/GitService.ts index 11aeef30cce3e7ec0c446346de8512f2c3b09040..d3f07e31516b90ecb1d82735de64082d2b8ecf6f 100644 --- a/apps/server/src/git/Layers/GitService.ts +++ b/apps/server/src/git/Layers/GitService.ts @@ -39,9 +39,9 @@ function toGitCommandError( }); } -const collectOutput = Effect.fn(function* ( +const collectOutput = Effect.fn(function* ( input: Pick, - stream: Stream.Stream, + stream: Stream.Stream, maxOutputBytes: number, ): Effect.fn.Return { const decoder = new TextDecoder(); diff --git a/apps/server/src/orchestration/projector.ts b/apps/server/src/orchestration/projector.ts index 296cac2cbeaefab204237d696fca7acf3c189bd0..bbc1cc8d014220bd262da605518aa9457c156116 100644 --- a/apps/server/src/orchestration/projector.ts +++ b/apps/server/src/orchestration/projector.ts @@ -40,9 +40,12 @@ function decodeForEvent( eventType: OrchestrationEvent["type"], field: string, ): Effect.Effect { - return Schema.decodeUnknownEffect(schema)(value).pipe( - Effect.mapError(toProjectorDecodeError(`${eventType}:${field}`)), - ) as Effect.Effect; + return Effect.try({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + try: () => Schema.decodeUnknownSync(schema as any)(value) as A, + catch: (error) => + toProjectorDecodeError(`${eventType}:${field}`)(error as Schema.SchemaError), + }); } function retainThreadMessagesAfterRevert( diff --git a/apps/server/src/serverLayers.ts b/apps/server/src/serverLayers.ts index 3d37cc105d1b7e007065fb43ebcaa276c4370778..da8def16858efaa6c276e9cf48e049f61f739441 100644 --- a/apps/server/src/serverLayers.ts +++ b/apps/server/src/serverLayers.ts @@ -17,6 +17,7 @@ import { ProviderCommandReactorLive } from "./orchestration/Layers/ProviderComma import { OrchestrationProjectionPipelineLive } from "./orchestration/Layers/ProjectionPipeline"; import { OrchestrationProjectionSnapshotQueryLive } from "./orchestration/Layers/ProjectionSnapshotQuery"; import { ProviderRuntimeIngestionLive } from "./orchestration/Layers/ProviderRuntimeIngestion"; +import { ProviderUnsupportedError } from "./provider/Errors"; import { makeCodexAdapterLive } from "./provider/Layers/CodexAdapter"; import { ProviderAdapterRegistryLive } from "./provider/Layers/ProviderAdapterRegistry"; import { makeProviderServiceLive } from "./provider/Layers/ProviderService"; @@ -35,7 +36,7 @@ import { NodePtyAdapterLive } from "./terminal/Layers/NodePTY"; export function makeServerProviderLayer(): Layer.Layer< ProviderService, - unknown, + ProviderUnsupportedError, SqlClient.SqlClient | ServerConfig > { return Effect.gen(function* () { diff --git a/apps/server/src/wsServer.test.ts b/apps/server/src/wsServer.test.ts index 6e177aa7f984dd41ae1dba21209bfcf8d050ba19..57abed02ac8d088199a99ca7ac49261913891706 100644 --- a/apps/server/src/wsServer.test.ts +++ b/apps/server/src/wsServer.test.ts @@ -323,14 +323,14 @@ describe("WebSocket Server", () => { async function createTestServer( options: { - persistenceLayer?: Layer.Layer; + persistenceLayer?: Layer.Layer; cwd?: string; autoBootstrapProjectFromCwd?: boolean; logWebSocketEvents?: boolean; devUrl?: string; authToken?: string; stateDir?: string; - providerLayer?: Layer.Layer; + providerLayer?: Layer.Layer; open?: OpenShape; gitManager?: GitManagerShape; gitCore?: Pick; diff --git a/apps/server/src/wsServer.ts b/apps/server/src/wsServer.ts index 85986f35e73892e99abef2d7e53b38bb1dc7bc53..aa72c851f9d8f3a0f33eb776edb1d0598ef2a4d4 100644 --- a/apps/server/src/wsServer.ts +++ b/apps/server/src/wsServer.ts @@ -66,14 +66,14 @@ export interface ServerShape { */ readonly start: Effect.Effect< http.Server, - unknown, + ServerLifecycleError, Scope.Scope | ServerRuntimeServices | ServerConfig >; /** * Wait for process shutdown signals. */ - readonly stopSignal: Effect.Effect; + readonly stopSignal: Effect.Effect; } /** @@ -165,7 +165,7 @@ class RouteRequestError extends Schema.TaggedErrorClass()("Ro export const createServer = Effect.fn(function* (): Effect.fn.Return< http.Server, - unknown, // TODO: This should not be unknown + ServerLifecycleError, Scope.Scope | ServerRuntimeServices | ServerConfig > { const serverConfig = yield* ServerConfig; @@ -338,21 +338,27 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return< yield* Scope.provide(orchestrationReactor.start, subscriptionsScope); if (autoBootstrapProjectFromCwd) { - const snapshot = yield* projectionReadModelQuery.getSnapshot(); - const existing = snapshot.projects.find((project) => project.workspaceRoot === cwd); - if (!existing) { - const createdAt = new Date().toISOString(); - const projectName = path.basename(cwd) || "project"; - yield* orchestrationEngine.dispatch({ - type: "project.create", - commandId: CommandId.makeUnsafe(crypto.randomUUID()), - projectId: ProjectId.makeUnsafe(crypto.randomUUID()), - title: projectName, - workspaceRoot: cwd, - defaultModel: "gpt-5-codex", - createdAt, - }); - } + yield* Effect.gen(function* () { + const snapshot = yield* projectionReadModelQuery.getSnapshot(); + const existing = snapshot.projects.find((project) => project.workspaceRoot === cwd); + if (!existing) { + const createdAt = new Date().toISOString(); + const projectName = path.basename(cwd) || "project"; + yield* orchestrationEngine.dispatch({ + type: "project.create", + commandId: CommandId.makeUnsafe(crypto.randomUUID()), + projectId: ProjectId.makeUnsafe(crypto.randomUUID()), + title: projectName, + workspaceRoot: cwd, + defaultModel: "gpt-5-codex", + createdAt, + }); + } + }).pipe( + Effect.mapError( + (cause) => new ServerLifecycleError({ operation: "autoBootstrapProject", cause }), + ), + ); } const routeRequest = Effect.fnUntraced(function* (request: WebSocketRequest) { @@ -618,7 +624,9 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return< ); yield* Effect.addFinalizer(() => Effect.sync(() => unsubscribeTerminalEvents())); - yield* NodeHttpServer.make(() => httpServer, listenOptions); + yield* NodeHttpServer.make(() => httpServer, listenOptions).pipe( + Effect.mapError((cause) => new ServerLifecycleError({ operation: "httpServerListen", cause })), + ); yield* Effect.addFinalizer(() => Effect.all([