110 lines · 4.4 KB · TypeScript
RawDownload
import {  AuthOrchestrationOperateScope,  AuthOrchestrationReadScope,  EnvironmentHttpApi,} from "@t3tools/contracts";import * as Effect from "effect/Effect";import * as Option from "effect/Option";import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder"; import { projectThreadDetailSnapshot } from "./ActivityPayloadProjection.ts";import { cleanupFailedUploadedAttachments, normalizeDispatchCommand } from "./Normalizer.ts";import {  annotateEnvironmentRequest,  failEnvironmentInternal,  failEnvironmentInvalidRequest,  failEnvironmentNotFound,  requireEnvironmentScope,} from "../auth/http.ts";import { OrchestrationEngineService } from "./Services/OrchestrationEngine.ts";import { ProjectionSnapshotQuery } from "./Services/ProjectionSnapshotQuery.ts"; export const orchestrationHttpApiLayer = HttpApiBuilder.group(  EnvironmentHttpApi,  "orchestration",  Effect.fnUntraced(function* (handlers) {    const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;    const orchestrationEngine = yield* OrchestrationEngineService;     return handlers      .handle(        "snapshot",        Effect.fn("environment.orchestration.snapshot")(function* (args) {          yield* annotateEnvironmentRequest(args.endpoint.name);          yield* requireEnvironmentScope(AuthOrchestrationReadScope);          // Serve the lightweight command read model (thread bodies empty)          // instead of the fully hydrated snapshot. Hydrating every message          // and activity payload in the database has OOM-killed servers, and          // the route's only consumer (the project CLI) reads projects alone —          // UI clients load the shell and per-thread snapshots instead.          return yield* projectionSnapshotQuery            .getCommandReadModel()            .pipe(              Effect.catch((cause) =>                failEnvironmentInternal("orchestration_snapshot_failed", cause),              ),            );        }),      )      .handle(        "shellSnapshot",        Effect.fn("environment.orchestration.shellSnapshot")(function* (args) {          yield* annotateEnvironmentRequest(args.endpoint.name);          yield* requireEnvironmentScope(AuthOrchestrationReadScope);          return yield* projectionSnapshotQuery            .getShellSnapshot()            .pipe(              Effect.catch((cause) =>                failEnvironmentInternal("orchestration_snapshot_failed", cause),              ),            );        }),      )      .handle(        "threadSnapshot",        Effect.fn("environment.orchestration.threadSnapshot")(function* (args) {          yield* annotateEnvironmentRequest(args.endpoint.name);          yield* requireEnvironmentScope(AuthOrchestrationReadScope);          const snapshot = yield* projectionSnapshotQuery            .getThreadDetailSnapshot(              args.params.threadId,              args.payload.turnLimit === undefined                ? undefined                : {                    turnLimit: args.payload.turnLimit,                    ...(args.payload.beforeCursor !== undefined                      ? { beforeCursor: args.payload.beforeCursor }                      : {}),                  },            )            .pipe(              Effect.catch((cause) =>                failEnvironmentInternal("orchestration_thread_snapshot_failed", cause),              ),            );          if (Option.isNone(snapshot)) {            return yield* failEnvironmentNotFound("thread_not_found");          }          return projectThreadDetailSnapshot(snapshot.value);        }),      )      .handle(        "dispatch",        Effect.fn("environment.orchestration.dispatch")(function* (args) {          yield* annotateEnvironmentRequest(args.endpoint.name);          yield* requireEnvironmentScope(AuthOrchestrationOperateScope);          const normalizedCommand = yield* normalizeDispatchCommand(args.payload).pipe(            Effect.catch(() => failEnvironmentInvalidRequest("invalid_command")),          );          return yield* orchestrationEngine.dispatch(normalizedCommand).pipe(            Effect.tapError(() =>              cleanupFailedUploadedAttachments(args.payload, normalizedCommand),            ),            Effect.catch((cause) =>              failEnvironmentInternal("orchestration_dispatch_failed", cause),            ),          );        }),      );  }),);