1855 lines · 74.2 KB · TypeScript
RawDownload
import * as Cause from "effect/Cause";import * as Crypto from "effect/Crypto";import * as DateTime from "effect/DateTime";import * as Duration from "effect/Duration";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Queue from "effect/Queue";import * as Ref from "effect/Ref";import * as Schema from "effect/Schema";import * as Stream from "effect/Stream";import {  DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL,  AuthOrchestrationOperateScope,  AuthOrchestrationReadScope,  AuthReviewWriteScope,  AuthRelayWriteScope,  AuthTerminalOperateScope,  AuthAccessReadScope,  AuthAccessStreamError,  type AuthAccessStreamEvent,  type AuthEnvironmentScope,  AuthSessionId,  CommandId,  type DiscoveredLocalServerList,  EventId,  type OrchestrationCommand,  type GitActionProgressEvent,  type GitManagerServiceError,  OrchestrationDispatchCommandError,  type OrchestrationEvent,  type OrchestrationShellStreamEvent,  OrchestrationGetFullThreadDiffError,  OrchestrationGetSnapshotError,  OrchestrationGetTurnDiffError,  ORCHESTRATION_WS_METHODS,  type ProjectEntriesFailure,  type ProjectFileFailure,  type ProjectFileOperation,  ProjectListEntriesError,  ProjectReadFileError,  ProjectSearchEntriesError,  ProjectWriteFileError,  RelayClientInstallFailedError,  type RelayClientInstallProgressEvent,  OrchestrationReplayEventsError,  type FilesystemBrowseFailure,  FilesystemBrowseError,  AssetWorkspaceContextNotFoundError,  AssetWorkspaceContextResolutionError,  EnvironmentAuthorizationError,  ThreadId,  type TerminalAttachStreamEvent,  type TerminalError,  type TerminalEvent,  type TerminalMetadataStreamEvent,  WS_METHODS,  WsRpcGroup,} from "@t3tools/contracts";import { clamp } from "effect/Number";import { HttpRouter, HttpServerRequest, HttpServerRespondable } from "effect/unstable/http";import { RpcSerialization, RpcServer } from "effect/unstable/rpc"; import * as CheckpointDiffQuery from "./checkpointing/CheckpointDiffQuery.ts";import * as ServerConfig from "./config.ts";import * as Keybindings from "./keybindings.ts";import * as ExternalLauncher from "./process/externalLauncher.ts";import { normalizeDispatchCommand } from "./orchestration/Normalizer.ts";import * as OrchestrationEngine from "./orchestration/Services/OrchestrationEngine.ts";import * as ProjectionSnapshotQuery from "./orchestration/Services/ProjectionSnapshotQuery.ts";import {  observeRpcEffect as instrumentRpcEffect,  observeRpcStream as instrumentRpcStream,  observeRpcStreamEffect as instrumentRpcStreamEffect,} from "./observability/RpcInstrumentation.ts";import * as ProviderRegistry from "./provider/Services/ProviderRegistry.ts";import * as ProviderMaintenanceRunner from "./provider/providerMaintenanceRunner.ts";import * as ServerLifecycleEvents from "./serverLifecycleEvents.ts";import * as ServerRuntimeStartup from "./serverRuntimeStartup.ts";import * as ServerSettings from "./serverSettings.ts";import * as TerminalManager from "./terminal/Manager.ts";import * as PreviewAutomationBroker from "./mcp/PreviewAutomationBroker.ts";import * as PreviewManager from "./preview/Manager.ts";import { issueAssetUrl } from "./assets/AssetAccess.ts";import * as PortScanner from "./preview/PortScanner.ts";import * as WorkspaceEntries from "./workspace/WorkspaceEntries.ts";import * as WorkspaceFileSystem from "./workspace/WorkspaceFileSystem.ts";import * as WorkspacePaths from "./workspace/WorkspacePaths.ts";import * as VcsStatusBroadcaster from "./vcs/VcsStatusBroadcaster.ts";import * as VcsProvisioningService from "./vcs/VcsProvisioningService.ts";import * as GitWorkflowService from "./git/GitWorkflowService.ts";import * as ReviewService from "./review/ReviewService.ts";import * as ProjectSetupScriptRunner from "./project/ProjectSetupScriptRunner.ts";import * as RepositoryIdentityResolver from "./project/RepositoryIdentityResolver.ts";import * as ServerEnvironment from "./environment/ServerEnvironment.ts";import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts";import * as ProcessDiagnostics from "./diagnostics/ProcessDiagnostics.ts";import * as ProcessResourceMonitor from "./diagnostics/ProcessResourceMonitor.ts";import * as TraceDiagnostics from "./diagnostics/TraceDiagnostics.ts";import * as SourceControlDiscovery from "./sourceControl/SourceControlDiscovery.ts";import * as SourceControlRepositoryService from "./sourceControl/SourceControlRepositoryService.ts";import * as AzureDevOpsCli from "./sourceControl/AzureDevOpsCli.ts";import * as BitbucketApi from "./sourceControl/BitbucketApi.ts";import * as GitHubCli from "./sourceControl/GitHubCli.ts";import * as GitLabCli from "./sourceControl/GitLabCli.ts";import * as SourceControlProviderRegistry from "./sourceControl/SourceControlProviderRegistry.ts";import * as GitVcsDriver from "./vcs/GitVcsDriver.ts";import * as VcsDriverRegistry from "./vcs/VcsDriverRegistry.ts";import * as VcsProjectConfig from "./vcs/VcsProjectConfig.ts";import * as VcsProcess from "./vcs/VcsProcess.ts";import * as PairingGrantStore from "./auth/PairingGrantStore.ts";import * as SessionStore from "./auth/SessionStore.ts";import { failEnvironmentAuthInvalid, failEnvironmentInternal } from "./auth/http.ts";import * as RelayClient from "@t3tools/shared/relayClient";const isOrchestrationDispatchCommandError = Schema.is(OrchestrationDispatchCommandError); const nowIso = Effect.map(DateTime.now, DateTime.formatIso); function unexpectedCompatibilityError(error: never): never {  throw new Error(`Unhandled compatibility error: ${String(error)}`);} /** Preserve the setup runner's broader pre-refactor message normalization. */function legacySetupFailureDescription(cause: unknown): string {  if (    typeof cause === "object" &&    cause !== null &&    "message" in cause &&    typeof cause.message === "string"  ) {    return cause.message;  }  return String(cause);} function projectEntriesFailureContext(error: WorkspaceEntries.WorkspaceEntriesError): {  readonly failure: ProjectEntriesFailure;  readonly normalizedCwd?: string;  readonly timeout?: string;  readonly detail?: string;} {  switch (error._tag) {    case "WorkspaceRootNotExistsError":      return {        failure: "workspace_root_not_found",        normalizedCwd: error.normalizedWorkspaceRoot,      };    case "WorkspaceRootCreateFailedError":      return {        failure: "workspace_root_create_failed",        normalizedCwd: error.normalizedWorkspaceRoot,      };    case "WorkspaceRootStatFailedError":      return {        failure: "workspace_root_stat_failed",        normalizedCwd: error.normalizedWorkspaceRoot,        detail: error.phase,      };    case "WorkspaceRootNotDirectoryError":      return {        failure: "workspace_root_not_directory",        normalizedCwd: error.normalizedWorkspaceRoot,      };    case "WorkspaceSearchIndexCreateFailed":      return {        failure: "search_index_create_failed",        normalizedCwd: error.cwd,        detail: error.reason,      };    case "WorkspaceSearchIndexScanTimedOut":      return {        failure: "search_index_scan_timed_out",        normalizedCwd: error.cwd,        timeout: error.timeout,      };    case "WorkspaceSearchIndexSearchFailed":      return {        failure: "search_index_search_failed",        normalizedCwd: error.cwd,        detail: error.reason,      };    default:      return unexpectedCompatibilityError(error);  }} function filesystemBrowseFailureContext(error: WorkspaceEntries.WorkspaceEntriesBrowseError): {  readonly failure: FilesystemBrowseFailure;  readonly parentPath?: string;  readonly platform?: string;} {  switch (error._tag) {    case "WorkspaceEntriesWindowsPathUnsupportedError":      return { failure: "windows_path_unsupported", platform: error.platform };    case "WorkspaceEntriesCurrentProjectRequiredError":      return { failure: "current_project_required" };    case "WorkspaceEntriesReadDirectoryError":      return { failure: "read_directory_failed", parentPath: error.parentPath };    default:      return unexpectedCompatibilityError(error);  }} function projectFileFailureContext(  error:    | WorkspaceFileSystem.WorkspaceFileSystemError    | WorkspacePaths.WorkspacePathOutsideRootError,): {  readonly failure: ProjectFileFailure;  readonly resolvedPath?: string;  readonly resolvedWorkspaceRoot?: string;  readonly operation?: ProjectFileOperation;  readonly operationPath?: string;} {  switch (error._tag) {    case "WorkspacePathOutsideRootError":      return { failure: "workspace_path_outside_root" };    case "WorkspaceFileSystemOperationError":      return {        failure: "operation_failed",        resolvedPath: error.resolvedPath,        operation: error.operation,        operationPath: error.operationPath,      };    case "WorkspaceFilePathEscapeError":      return {        failure: "resolved_path_outside_root",        resolvedPath: error.resolvedPath,        resolvedWorkspaceRoot: error.resolvedWorkspaceRoot,      };    case "WorkspacePathNotFileError":      return { failure: "path_not_file", resolvedPath: error.resolvedPath };    case "WorkspaceBinaryFileError":      return { failure: "binary_file", resolvedPath: error.resolvedPath };    default:      return unexpectedCompatibilityError(error);  }} function projectSetupScriptCompatibilityDetail(  error: ProjectSetupScriptRunner.ProjectSetupScriptRunnerError,): string {  switch (error._tag) {    case "ProjectSetupScriptOperationError":      return legacySetupFailureDescription(error.cause);    case "ProjectSetupScriptProjectNotFoundError":      return "Project was not found for setup script execution.";    default:      return unexpectedCompatibilityError(error);  }} function isThreadDetailEvent(event: OrchestrationEvent): event is Extract<  OrchestrationEvent,  {    type:      | "thread.message-sent"      | "thread.proposed-plan-upserted"      | "thread.activity-appended"      | "thread.turn-diff-completed"      | "thread.reverted"      | "thread.session-set";  }> {  return (    event.type === "thread.message-sent" ||    event.type === "thread.proposed-plan-upserted" ||    event.type === "thread.activity-appended" ||    event.type === "thread.turn-diff-completed" ||    event.type === "thread.reverted" ||    event.type === "thread.session-set"  );} const PROVIDER_STATUS_DEBOUNCE_MS = 200; const RPC_REQUIRED_SCOPE = new Map<string, AuthEnvironmentScope>([  [ORCHESTRATION_WS_METHODS.dispatchCommand, AuthOrchestrationOperateScope],  [ORCHESTRATION_WS_METHODS.getTurnDiff, AuthOrchestrationReadScope],  [ORCHESTRATION_WS_METHODS.getFullThreadDiff, AuthOrchestrationReadScope],  [ORCHESTRATION_WS_METHODS.replayEvents, AuthOrchestrationReadScope],  [ORCHESTRATION_WS_METHODS.subscribeShell, AuthOrchestrationReadScope],  [ORCHESTRATION_WS_METHODS.getArchivedShellSnapshot, AuthOrchestrationReadScope],  [ORCHESTRATION_WS_METHODS.subscribeThread, AuthOrchestrationReadScope],  [WS_METHODS.serverGetConfig, AuthOrchestrationReadScope],  [WS_METHODS.serverRefreshProviders, AuthOrchestrationOperateScope],  [WS_METHODS.serverUpdateProvider, AuthOrchestrationOperateScope],  [WS_METHODS.serverUpsertKeybinding, AuthOrchestrationOperateScope],  [WS_METHODS.serverRemoveKeybinding, AuthOrchestrationOperateScope],  [WS_METHODS.serverGetSettings, AuthOrchestrationReadScope],  [WS_METHODS.serverUpdateSettings, AuthOrchestrationOperateScope],  [WS_METHODS.serverDiscoverSourceControl, AuthOrchestrationReadScope],  [WS_METHODS.serverGetTraceDiagnostics, AuthOrchestrationReadScope],  [WS_METHODS.serverGetProcessDiagnostics, AuthOrchestrationReadScope],  [WS_METHODS.serverGetProcessResourceHistory, AuthOrchestrationReadScope],  [WS_METHODS.serverSignalProcess, AuthOrchestrationOperateScope],  [WS_METHODS.cloudGetRelayClientStatus, AuthRelayWriteScope],  [WS_METHODS.cloudInstallRelayClient, AuthRelayWriteScope],  [WS_METHODS.sourceControlLookupRepository, AuthOrchestrationReadScope],  [WS_METHODS.sourceControlCloneRepository, AuthOrchestrationOperateScope],  [WS_METHODS.sourceControlPublishRepository, AuthOrchestrationOperateScope],  [WS_METHODS.projectsListEntries, AuthOrchestrationReadScope],  [WS_METHODS.projectsReadFile, AuthOrchestrationReadScope],  [WS_METHODS.projectsSearchEntries, AuthOrchestrationReadScope],  [WS_METHODS.projectsWriteFile, AuthOrchestrationOperateScope],  [WS_METHODS.shellOpenInEditor, AuthOrchestrationOperateScope],  [WS_METHODS.filesystemBrowse, AuthOrchestrationReadScope],  [WS_METHODS.assetsCreateUrl, AuthOrchestrationReadScope],  [WS_METHODS.subscribeVcsStatus, AuthOrchestrationReadScope],  [WS_METHODS.vcsRefreshStatus, AuthOrchestrationReadScope],  [WS_METHODS.vcsPull, AuthOrchestrationOperateScope],  [WS_METHODS.gitRunStackedAction, AuthOrchestrationOperateScope],  [WS_METHODS.gitResolvePullRequest, AuthOrchestrationOperateScope],  [WS_METHODS.gitPreparePullRequestThread, AuthOrchestrationOperateScope],  [WS_METHODS.vcsListRefs, AuthOrchestrationReadScope],  [WS_METHODS.vcsCreateWorktree, AuthOrchestrationOperateScope],  [WS_METHODS.vcsRemoveWorktree, AuthOrchestrationOperateScope],  [WS_METHODS.vcsCreateRef, AuthOrchestrationOperateScope],  [WS_METHODS.vcsSwitchRef, AuthOrchestrationOperateScope],  [WS_METHODS.vcsInit, AuthOrchestrationOperateScope],  [WS_METHODS.reviewGetDiffPreview, AuthReviewWriteScope],  [WS_METHODS.terminalOpen, AuthTerminalOperateScope],  [WS_METHODS.terminalAttach, AuthTerminalOperateScope],  [WS_METHODS.terminalWrite, AuthTerminalOperateScope],  [WS_METHODS.terminalResize, AuthTerminalOperateScope],  [WS_METHODS.terminalClear, AuthTerminalOperateScope],  [WS_METHODS.terminalRestart, AuthTerminalOperateScope],  [WS_METHODS.terminalClose, AuthTerminalOperateScope],  [WS_METHODS.subscribeTerminalEvents, AuthTerminalOperateScope],  [WS_METHODS.subscribeTerminalMetadata, AuthTerminalOperateScope],  [WS_METHODS.previewOpen, AuthOrchestrationOperateScope],  [WS_METHODS.previewNavigate, AuthOrchestrationOperateScope],  [WS_METHODS.previewRefresh, AuthOrchestrationOperateScope],  [WS_METHODS.previewClose, AuthOrchestrationOperateScope],  [WS_METHODS.previewList, AuthOrchestrationReadScope],  [WS_METHODS.previewReportStatus, AuthOrchestrationOperateScope],  [WS_METHODS.previewAutomationConnect, AuthOrchestrationOperateScope],  [WS_METHODS.previewAutomationRespond, AuthOrchestrationOperateScope],  [WS_METHODS.previewAutomationReportOwner, AuthOrchestrationOperateScope],  [WS_METHODS.previewAutomationClearOwner, AuthOrchestrationOperateScope],  [WS_METHODS.subscribePreviewEvents, AuthOrchestrationReadScope],  [WS_METHODS.subscribeDiscoveredLocalServers, AuthOrchestrationReadScope],  [WS_METHODS.subscribeServerConfig, AuthOrchestrationReadScope],  [WS_METHODS.subscribeServerLifecycle, AuthOrchestrationReadScope],  [WS_METHODS.subscribeAuthAccess, AuthAccessReadScope],]); function toAuthAccessStreamEvent(  change: PairingGrantStore.BootstrapCredentialChange | SessionStore.SessionCredentialChange,  revision: number,  currentSessionId: AuthSessionId,): AuthAccessStreamEvent {  switch (change.type) {    case "pairingLinkUpserted":      return {        version: 1,        revision,        type: "pairingLinkUpserted",        payload: change.pairingLink,      };    case "pairingLinkRemoved":      return {        version: 1,        revision,        type: "pairingLinkRemoved",        payload: { id: change.id },      };    case "clientUpserted":      return {        version: 1,        revision,        type: "clientUpserted",        payload: {          ...change.clientSession,          current: change.clientSession.sessionId === currentSessionId,        },      };    case "clientRemoved":      return {        version: 1,        revision,        type: "clientRemoved",        payload: { sessionId: change.sessionId },      };  }} const makeWsRpcLayer = (currentSession: EnvironmentAuth.AuthenticatedSession) =>  WsRpcGroup.toLayer(    Effect.gen(function* () {      const currentSessionId = currentSession.sessionId;      const crypto = yield* Crypto.Crypto;      const projectionSnapshotQuery = yield* ProjectionSnapshotQuery.ProjectionSnapshotQuery;      const orchestrationEngine = yield* OrchestrationEngine.OrchestrationEngineService;      const checkpointDiffQuery = yield* CheckpointDiffQuery.CheckpointDiffQuery;      const keybindings = yield* Keybindings.Keybindings;      const externalLauncher = yield* ExternalLauncher.ExternalLauncher;      const gitWorkflow = yield* GitWorkflowService.GitWorkflowService;      const review = yield* ReviewService.ReviewService;      const vcsProvisioning = yield* VcsProvisioningService.VcsProvisioningService;      const vcsStatusBroadcaster = yield* VcsStatusBroadcaster.VcsStatusBroadcaster;      const terminalManager = yield* TerminalManager.TerminalManager;      const previewAutomationBroker = yield* PreviewAutomationBroker.PreviewAutomationBroker;      const previewManager = yield* PreviewManager.PreviewManager;      const portDiscovery = yield* PortScanner.PortDiscovery;      const providerRegistry = yield* ProviderRegistry.ProviderRegistry;      const providerMaintenanceRunner = yield* ProviderMaintenanceRunner.ProviderMaintenanceRunner;      const config = yield* ServerConfig.ServerConfig;      const lifecycleEvents = yield* ServerLifecycleEvents.ServerLifecycleEvents;      const serverSettings = yield* ServerSettings.ServerSettingsService;      const startup = yield* ServerRuntimeStartup.ServerRuntimeStartup;      const workspaceEntries = yield* WorkspaceEntries.WorkspaceEntries;      const workspaceFileSystem = yield* WorkspaceFileSystem.WorkspaceFileSystem;      const projectSetupScriptRunner = yield* ProjectSetupScriptRunner.ProjectSetupScriptRunner;      const repositoryIdentityResolver =        yield* RepositoryIdentityResolver.RepositoryIdentityResolver;      const serverEnvironment = yield* ServerEnvironment.ServerEnvironment;      const serverAuth = yield* EnvironmentAuth.EnvironmentAuth;      const sourceControlDiscovery = yield* SourceControlDiscovery.SourceControlDiscovery;      const automaticGitFetchInterval = serverSettings.getSettings.pipe(        Effect.map((settings) => settings.automaticGitFetchInterval),        Effect.catch((cause) =>          Effect.logWarning("Failed to read automatic Git fetch interval setting", {            detail: cause.message,          }).pipe(Effect.as(DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL)),        ),      );      const sourceControlRepositories =        yield* SourceControlRepositoryService.SourceControlRepositoryService;      const bootstrapCredentials = yield* PairingGrantStore.PairingGrantStore;      const sessions = yield* SessionStore.SessionStore;      const processDiagnostics = yield* ProcessDiagnostics.ProcessDiagnostics;      const processResourceMonitor = yield* ProcessResourceMonitor.ProcessResourceMonitor;      const relayClient = yield* RelayClient.RelayClient;      const authorizationError = (requiredScope: AuthEnvironmentScope) =>        new EnvironmentAuthorizationError({          message: `The authenticated token is missing required scope: ${requiredScope}.`,          requiredScope,        });      const authorizeEffect = <A, E, R>(        requiredScope: AuthEnvironmentScope,        effect: Effect.Effect<A, E, R>,      ): Effect.Effect<A, E | EnvironmentAuthorizationError, R> =>        currentSession.scopes.includes(requiredScope)          ? effect          : Effect.fail(authorizationError(requiredScope));      const authorizeStream = <A, E, R>(        requiredScope: AuthEnvironmentScope,        stream: Stream.Stream<A, E, R>,      ): Stream.Stream<A, E | EnvironmentAuthorizationError, R> =>        currentSession.scopes.includes(requiredScope)          ? stream          : Stream.fail(authorizationError(requiredScope));      const requiredScopeForMethod = (method: string): AuthEnvironmentScope => {        const requiredScope = RPC_REQUIRED_SCOPE.get(method);        if (requiredScope === undefined) {          throw new Error(`RPC method ${method} has no declared authorization scope.`);        }        return requiredScope;      };      const observeRpcEffect = <A, E, R>(        method: string,        effect: Effect.Effect<A, E, R>,        traceAttributes?: Readonly<Record<string, unknown>>,      ) =>        instrumentRpcEffect(          method,          authorizeEffect(requiredScopeForMethod(method), effect),          traceAttributes,        );      const observeRpcStream = <A, E, R>(        method: string,        stream: Stream.Stream<A, E, R>,        traceAttributes?: Readonly<Record<string, unknown>>,      ) =>        instrumentRpcStream(          method,          authorizeStream(requiredScopeForMethod(method), stream),          traceAttributes,        );      const observeRpcStreamEffect = <A, StreamError, StreamContext, EffectError, EffectContext>(        method: string,        effect: Effect.Effect<          Stream.Stream<A, StreamError, StreamContext>,          EffectError,          EffectContext        >,        traceAttributes?: Readonly<Record<string, unknown>>,      ) =>        instrumentRpcStreamEffect(          method,          authorizeEffect(requiredScopeForMethod(method), effect),          traceAttributes,        );      const toDispatchCommandError = (cause: unknown, fallbackMessage: string) =>        isOrchestrationDispatchCommandError(cause)          ? cause          : new OrchestrationDispatchCommandError({              message: cause instanceof Error ? cause.message : fallbackMessage,              cause,

Lines 1–500 of 1855.