import * as DateTime from "effect/DateTime";import * as Duration from "effect/Duration";import * as Encoding from "effect/Encoding";import * as Effect from "effect/Effect";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Path from "effect/Path";import * as Queue from "effect/Queue";import * as Ref from "effect/Ref";import * as Schema from "effect/Schema";import * as Result from "effect/Result";import * as Stream from "effect/Stream";import { DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL, AuthAccessStreamError, type AuthAccessStreamEvent, type AuthEnvironmentScope, AuthSessionId, ClientConnectionMethod, ClientDeviceType, ClientOs, ClientSurface, ClientWebDeployment, type DiscoveredLocalServerList, type EditorId, type FileManagerRevealKind, type OrchestrationClientOrigin, type OrchestrationV2Command, type GitActionProgressEvent, type GitManagerServiceError, type MessageId, OrchestrationGetFullThreadDiffError, OrchestrationSearchThreadsError, OrchestrationGetTurnDiffError, ORCHESTRATION_V2_WS_METHODS, ORCHESTRATION_PROTOCOL_QUERY_PARAM, ORCHESTRATION_PROTOCOL_VERSION, OrchestrationV2DispatchCommandError, OrchestrationV2GetShellSnapshotError, OrchestrationV2GetThreadProjectionError, OrchestrationV2ThreadLaunchError, type OrchestrationProjectShell, type OrchestrationV2ShellSnapshot, type ProjectEntriesFailure, type ProjectFileFailure, type ProjectFileOperation, type ProjectMutation, ProjectListEntriesError, ProjectReadFileError, ProjectSearchContentsError, ProjectSearchEntriesError, ProjectWriteFileError, ProjectMutationError, ProviderUploadFeedbackError, ProviderSetupError, RelayClientInstallFailedError, type RelayClientInstallProgressEvent, type ServerSelfUpdateError, type ServerSelfUpdateProgressEvent, type FilesystemBrowseFailure, FilesystemBrowseError, AssetWorkspaceContextNotFoundError, AssetWorkspaceContextResolutionError, ChatAttachmentId, PersistChatAttachmentsError, RpcClientId, EnvironmentAuthorizationError, ThreadId, type TerminalAttachStreamEvent, type TerminalError, type TerminalEvent, type TerminalMetadataStreamEvent, WS_METHODS, WsRpcGroup,} from "@t3tools/contracts";import { resolveServerBackgroundActivitySettings } from "@t3tools/shared/backgroundActivitySettings";import { HttpRouter, HttpServerRequest, HttpServerRespondable, HttpServerResponse,} from "effect/unstable/http";import { RpcSerialization, RpcServer } from "effect/unstable/rpc";import * as SqlClient from "effect/unstable/sql/SqlClient"; import * as CheckpointDiffQuery from "./checkpointing/CheckpointDiffQuery.ts";import * as ServerConfig from "./config.ts";import * as EnvironmentTheme from "./environmentTheme.ts";import * as Keybindings from "./keybindings.ts";import * as ExternalLauncher from "./process/externalLauncher.ts";import * as ThreadManagementService from "./orchestration-v2/ThreadManagementService.ts";import { ProviderSessionManagerV2 } from "./orchestration-v2/ProviderSessionManager.ts";import * as ThreadLaunchService from "./orchestration-v2/ThreadLaunchService.ts";import * as ScheduledTasks from "./scheduledTasks/ScheduledTaskService.ts";import { archivedShellStreamItemFromThreadShell, buildActiveShellSnapshot, coalesceShellApplicationEvents, coalesceStoredThreadEvents, composeShellStreamWithEnrichment, shellStreamItemFromEnrichmentRefresh, shellStreamItemFromThreadShell, shellStreamItemsFromInitialSnapshot, shellStreamItemsFromResumeSnapshot, toShellApplicationEvent, type ShellApplicationEvent,} from "./orchestration-v2/ShellStream.ts";import { ORCHESTRATION_V2_PROJECTION_SCHEMA_VERSION } from "./orchestration-v2/ProjectionStore.ts";import { bufferLiveStream } from "./orchestration/LiveStreamBudget.ts";import { coalesceThreadLiveStream } from "./orchestration-v2/ThreadLiveEventCoalescer.ts";import { decideThreadResume, threadReplayEncodedBytes, THREAD_RESUME_MAX_REPLAY_EVENTS,} from "./orchestration-v2/ThreadStream.ts";import { projectDomainEventForWire, projectThreadProjectionForWire,} from "./orchestration-v2/WireProjection.ts";import * as ProjectionSnapshotQuery from "./orchestration/Services/ProjectionSnapshotQuery.ts";import * as OrchestrationEventStore from "./persistence/Services/OrchestrationEventStore.ts";import { userFacingDispatchErrorMessage } from "./orchestration-v2/UserFacingErrors.ts";import { attachmentIsPendingUpload, claimPendingAttachments, releaseClaimedAttachments,} from "./orchestration-v2/AttachmentClaims.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 { ProviderAuthService } from "./provider/Services/ProviderAuthService.ts";import { ProviderInstanceRegistry } from "./provider/Services/ProviderInstanceRegistry.ts";import { makeProviderInstallation } from "./provider/providerInstallation.ts";import * as ServerSelfUpdate from "./cloud/selfUpdate.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 { attachmentRelativePath, createDeterministicAttachmentId } from "./attachmentStore.ts";import { parseBase64DataUrl } from "./imageMime.ts";import { deletePendingAttachment, issueAttachmentUploadUrl } from "./assets/AttachmentUpload.ts";import * as PortScanner from "./preview/PortScanner.ts";import * as WorkspaceEntries from "./workspace/WorkspaceEntries.ts";import * as WorkspaceFileSystem from "./workspace/WorkspaceFileSystem.ts";import { readWorkflowScript } from "./orchestration/workflowScriptQuery.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 ProjectEnrichmentService from "./project/ProjectEnrichmentService.ts";import * as ProjectService from "./project/ProjectService.ts";import * as ServerEnvironment from "./environment/ServerEnvironment.ts";import * as RemoteOpenTargets from "./environment/RemoteOpenTargets.ts";import * as BackgroundPolicy from "./background/BackgroundPolicy.ts";import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts";import { requiredScopeForRpcMethod } from "./auth/RpcAuthorization.ts";import * as ProcessDiagnostics from "./diagnostics/ProcessDiagnostics.ts";import * as ProcessResourceMonitor from "./diagnostics/ProcessResourceMonitor.ts";import * as ResourceTelemetry from "./resourceTelemetry/ResourceTelemetry.ts";import * as AnalyticsService from "./telemetry/AnalyticsService.ts";import * as UsageService from "./usage/UsageService.ts";import * as TraceDiagnostics from "./diagnostics/TraceDiagnostics.ts";import * as PullRequestService from "./pullRequest/PullRequestService.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 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 CONFIG_DISCOVERY_TIMEOUT = Duration.seconds(5);const isProviderUploadFeedbackError = Schema.is(ProviderUploadFeedbackError); const resolveDiscoveryForConfig = <A, E, R>( discovery: Effect.Effect<A, E, R>, onTimeout: () => A,) => discovery.pipe( Effect.timeoutOption(CONFIG_DISCOVERY_TIMEOUT), Effect.map(Option.getOrElse(onTimeout)), ); export const resolveAvailableEditorsForConfig = <A, E, R>( discovery: Effect.Effect<ReadonlyArray<A>, E, R>,) => resolveDiscoveryForConfig(discovery, () => []); export const resolveFileManagerRevealKindForConfig = <E, R>( discovery: Effect.Effect<FileManagerRevealKind | undefined, E, R>,) => resolveDiscoveryForConfig(discovery, () => undefined); function unexpectedCompatibilityError(error: never): never { throw new Error(`Unhandled compatibility error: ${String(error)}`);} const persistChatAttachments = Effect.fn("ws.assets.persistChatAttachments")(function* (input: { readonly threadId: ThreadId; readonly messageId: MessageId; readonly attachments: ReadonlyArray<{ readonly type: "image"; readonly name: string; readonly mimeType: string; readonly sizeBytes: number; readonly dataUrl: string; }>;}) { const config = yield* ServerConfig.ServerConfig; const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; return yield* Effect.forEach( input.attachments.map((attachment, index) => ({ attachment, index })), Effect.fn("ws.assets.persistChatAttachment")(function* ({ attachment, index }) { const parsed = parseBase64DataUrl(attachment.dataUrl); if (parsed === null || parsed.mimeType !== attachment.mimeType.toLowerCase()) { return yield* new PersistChatAttachmentsError({ message: `Attachment ${attachment.name} has an invalid image payload.`, }); } const bytes = yield* Effect.fromResult(Encoding.decodeBase64(parsed.base64)).pipe( Effect.mapError( (cause) => new PersistChatAttachmentsError({ message: `Attachment ${attachment.name} is not valid base64.`, cause, }), ), ); if (bytes.byteLength !== attachment.sizeBytes) { return yield* new PersistChatAttachmentsError({ message: `Attachment ${attachment.name} size does not match its payload.`, }); } const rawId = createDeterministicAttachmentId(input.threadId, `${input.messageId}:${index}`); if (rawId === null) { return yield* new PersistChatAttachmentsError({ message: "Could not allocate an attachment identifier.", }); } const persisted = { type: "image" as const, id: ChatAttachmentId.make(rawId), name: attachment.name, mimeType: attachment.mimeType, sizeBytes: attachment.sizeBytes, }; yield* fileSystem .writeFile(path.join(config.attachmentsDir, attachmentRelativePath(persisted)!), bytes) .pipe( Effect.mapError( (cause) => new PersistChatAttachmentsError({ message: `Could not persist attachment ${attachment.name}.`, cause, }), ), ); return persisted; }), { concurrency: 2 }, );}); 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); }} const PROVIDER_STATUS_DEBOUNCE_MS = 200; const ServerWsRpcGroup = WsRpcGroup;// When a resuming client's cursor is more than this many events behind the// current head, skip the per-event catch-up replay and send a fresh shell// snapshot instead. Replaying each intervening event costs a shell refetch;// past this gap a single O(active-threads) snapshot is cheaper and bounded.// Matches the event store's default page size (DEFAULT_READ_FROM_SEQUENCE_LIMIT).const SHELL_RESUME_MAX_GAP = 1_000;// Row count alone does not bound replay memory: a few events with large tool// payloads can decode to gigabytes. Before replaying, sum the serialized// payload bytes of the range in SQL and reset with a snapshot past this budget.const ORCHESTRATION_REPLAY_PAYLOAD_BUDGET_BYTES = 8 * 1024 * 1024; 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 isClientSurface = Schema.is(ClientSurface);const isClientConnectionMethod = Schema.is(ClientConnectionMethod);const isClientDeviceType = Schema.is(ClientDeviceType);const isClientOs = Schema.is(ClientOs);const isClientWebDeployment = Schema.is(ClientWebDeployment);const MAX_CLIENT_APP_VERSION_LENGTH = 64;const MAX_CLIENT_BROWSER_LENGTH = 64;const MAX_CLIENT_DEVICE_MODEL_LENGTH = 80; export function hasCompatibleOrchestrationProtocol(url: URL): boolean { return ( url.searchParams.get(ORCHESTRATION_PROTOCOL_QUERY_PARAM) === String(ORCHESTRATION_PROTOCOL_VERSION) );} // Optional client identity announced on the /ws upgrade URL next to wsTicket.// Lenient by design: absent or malformed values degrade to {} so a connection// never fails over attribution metadata.function readClientConnectionOrigin( request: HttpServerRequest.HttpServerRequest,): OrchestrationClientOrigin { const url = HttpServerRequest.toURL(request); if (Option.isNone(url)) { return {}; } const surface = url.value.searchParams.get("clientSurface"); const appVersion = url.value.searchParams.get("clientAppVersion")?.trim() ?? ""; return { ...(isClientSurface(surface) ? { surface } : {}), ...(appVersion !== "" && appVersion.length <= MAX_CLIENT_APP_VERSION_LENGTH ? { appVersion } : {}), };} // Client telemetry stays in this socket's RPC layer. It must not become a// server-global "current client" because several client types can connect at once.function readClientAnalyticsProps(request: HttpServerRequest.HttpServerRequest) { const url = HttpServerRequest.toURL(request); if (Option.isNone(url)) { return {}; } const surface = url.value.searchParams.get("clientSurface"); const appVersion = url.value.searchParams.get("clientAppVersion")?.trim() ?? ""; const deviceType = url.value.searchParams.get("clientDeviceType"); const os = url.value.searchParams.get("clientOs"); const webDeployment = url.value.searchParams.get("clientWebDeployment"); const browser = url.value.searchParams.get("clientBrowser")?.trim() ?? ""; const connectionMethod = url.value.searchParams.get("connectionMethod"); const rawOsMajorVersion = url.value.searchParams.get("clientOsMajorVersion") ?? ""; const osMajorVersion = Number(rawOsMajorVersion); const deviceModel = url.value.searchParams.get("clientDeviceModel")?.trim() ?? ""; const isMobile = surface === "mobile"; const hasOsMajorVersion = isMobile && rawOsMajorVersion !== "" && Number.isInteger(osMajorVersion) && osMajorVersion > 0; const hasDeviceModel = isMobile && deviceModel !== "" && deviceModel.length <= MAX_CLIENT_DEVICE_MODEL_LENGTH; return { ...(isClientSurface(surface) ? { surface } : {}), ...(appVersion !== "" && appVersion.length <= MAX_CLIENT_APP_VERSION_LENGTH ? { appVersion, clientAppVersion: appVersion }Lines 1–500 of 2781. Load more
import * as DateTime from "effect/DateTime"; import * as Duration from "effect/Duration"; import * as Encoding from "effect/Encoding"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as Path from "effect/Path"; import * as Queue from "effect/Queue"; import * as Ref from "effect/Ref"; import * as Schema from "effect/Schema"; import * as Result from "effect/Result"; import * as Stream from "effect/Stream"; import { DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL, AuthAccessStreamError, type AuthAccessStreamEvent, type AuthEnvironmentScope, AuthSessionId, ClientConnectionMethod, ClientDeviceType, ClientOs, ClientSurface, ClientWebDeployment, type DiscoveredLocalServerList, type EditorId, type FileManagerRevealKind, type OrchestrationClientOrigin, type OrchestrationV2Command, type GitActionProgressEvent, type GitManagerServiceError, type MessageId, OrchestrationGetFullThreadDiffError, OrchestrationSearchThreadsError, OrchestrationGetTurnDiffError, ORCHESTRATION_V2_WS_METHODS, ORCHESTRATION_PROTOCOL_QUERY_PARAM, ORCHESTRATION_PROTOCOL_VERSION, OrchestrationV2DispatchCommandError, OrchestrationV2GetShellSnapshotError, OrchestrationV2GetThreadProjectionError, OrchestrationV2ThreadLaunchError, type OrchestrationProjectShell, type OrchestrationV2ShellSnapshot, type ProjectEntriesFailure, type ProjectFileFailure, type ProjectFileOperation, type ProjectMutation, ProjectListEntriesError, ProjectReadFileError, ProjectSearchContentsError, ProjectSearchEntriesError, ProjectWriteFileError, ProjectMutationError, ProviderUploadFeedbackError, ProviderSetupError, RelayClientInstallFailedError, type RelayClientInstallProgressEvent, type ServerSelfUpdateError, type ServerSelfUpdateProgressEvent, type FilesystemBrowseFailure, FilesystemBrowseError, AssetWorkspaceContextNotFoundError, AssetWorkspaceContextResolutionError, ChatAttachmentId, PersistChatAttachmentsError, RpcClientId, EnvironmentAuthorizationError, ThreadId, type TerminalAttachStreamEvent, type TerminalError, type TerminalEvent, type TerminalMetadataStreamEvent, WS_METHODS, WsRpcGroup, } from "@t3tools/contracts"; import { resolveServerBackgroundActivitySettings } from "@t3tools/shared/backgroundActivitySettings"; import { HttpRouter, HttpServerRequest, HttpServerRespondable, HttpServerResponse, } from "effect/unstable/http"; import { RpcSerialization, RpcServer } from "effect/unstable/rpc"; import * as SqlClient from "effect/unstable/sql/SqlClient"; import * as CheckpointDiffQuery from "./checkpointing/CheckpointDiffQuery.ts"; import * as ServerConfig from "./config.ts"; import * as EnvironmentTheme from "./environmentTheme.ts"; import * as Keybindings from "./keybindings.ts"; import * as ExternalLauncher from "./process/externalLauncher.ts"; import * as ThreadManagementService from "./orchestration-v2/ThreadManagementService.ts"; import { ProviderSessionManagerV2 } from "./orchestration-v2/ProviderSessionManager.ts"; import * as ThreadLaunchService from "./orchestration-v2/ThreadLaunchService.ts"; import * as ScheduledTasks from "./scheduledTasks/ScheduledTaskService.ts"; import { archivedShellStreamItemFromThreadShell, buildActiveShellSnapshot, coalesceShellApplicationEvents, coalesceStoredThreadEvents, composeShellStreamWithEnrichment, shellStreamItemFromEnrichmentRefresh, shellStreamItemFromThreadShell, shellStreamItemsFromInitialSnapshot, shellStreamItemsFromResumeSnapshot, toShellApplicationEvent, type ShellApplicationEvent, } from "./orchestration-v2/ShellStream.ts"; import { ORCHESTRATION_V2_PROJECTION_SCHEMA_VERSION } from "./orchestration-v2/ProjectionStore.ts"; import { bufferLiveStream } from "./orchestration/LiveStreamBudget.ts"; import { coalesceThreadLiveStream } from "./orchestration-v2/ThreadLiveEventCoalescer.ts"; import { decideThreadResume, threadReplayEncodedBytes, THREAD_RESUME_MAX_REPLAY_EVENTS, } from "./orchestration-v2/ThreadStream.ts"; import { projectDomainEventForWire, projectThreadProjectionForWire, } from "./orchestration-v2/WireProjection.ts"; import * as ProjectionSnapshotQuery from "./orchestration/Services/ProjectionSnapshotQuery.ts"; import * as OrchestrationEventStore from "./persistence/Services/OrchestrationEventStore.ts"; import { userFacingDispatchErrorMessage } from "./orchestration-v2/UserFacingErrors.ts"; import { attachmentIsPendingUpload, claimPendingAttachments, releaseClaimedAttachments, } from "./orchestration-v2/AttachmentClaims.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 { ProviderAuthService } from "./provider/Services/ProviderAuthService.ts"; import { ProviderInstanceRegistry } from "./provider/Services/ProviderInstanceRegistry.ts"; import { makeProviderInstallation } from "./provider/providerInstallation.ts"; import * as ServerSelfUpdate from "./cloud/selfUpdate.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 { attachmentRelativePath, createDeterministicAttachmentId } from "./attachmentStore.ts"; import { parseBase64DataUrl } from "./imageMime.ts"; import { deletePendingAttachment, issueAttachmentUploadUrl } from "./assets/AttachmentUpload.ts"; import * as PortScanner from "./preview/PortScanner.ts"; import * as WorkspaceEntries from "./workspace/WorkspaceEntries.ts"; import * as WorkspaceFileSystem from "./workspace/WorkspaceFileSystem.ts"; import { readWorkflowScript } from "./orchestration/workflowScriptQuery.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 ProjectEnrichmentService from "./project/ProjectEnrichmentService.ts"; import * as ProjectService from "./project/ProjectService.ts"; import * as ServerEnvironment from "./environment/ServerEnvironment.ts"; import * as RemoteOpenTargets from "./environment/RemoteOpenTargets.ts"; import * as BackgroundPolicy from "./background/BackgroundPolicy.ts"; import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts"; import { requiredScopeForRpcMethod } from "./auth/RpcAuthorization.ts"; import * as ProcessDiagnostics from "./diagnostics/ProcessDiagnostics.ts"; import * as ProcessResourceMonitor from "./diagnostics/ProcessResourceMonitor.ts"; import * as ResourceTelemetry from "./resourceTelemetry/ResourceTelemetry.ts"; import * as AnalyticsService from "./telemetry/AnalyticsService.ts"; import * as UsageService from "./usage/UsageService.ts"; import * as TraceDiagnostics from "./diagnostics/TraceDiagnostics.ts"; import * as PullRequestService from "./pullRequest/PullRequestService.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 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 CONFIG_DISCOVERY_TIMEOUT = Duration.seconds(5); const isProviderUploadFeedbackError = Schema.is(ProviderUploadFeedbackError); const resolveDiscoveryForConfig = <A, E, R>( discovery: Effect.Effect<A, E, R>, onTimeout: () => A, ) => discovery.pipe( Effect.timeoutOption(CONFIG_DISCOVERY_TIMEOUT), Effect.map(Option.getOrElse(onTimeout)), ); export const resolveAvailableEditorsForConfig = <A, E, R>( discovery: Effect.Effect<ReadonlyArray<A>, E, R>, ) => resolveDiscoveryForConfig(discovery, () => []); export const resolveFileManagerRevealKindForConfig = <E, R>( discovery: Effect.Effect<FileManagerRevealKind | undefined, E, R>, ) => resolveDiscoveryForConfig(discovery, () => undefined); function unexpectedCompatibilityError(error: never): never { throw new Error(`Unhandled compatibility error: ${String(error)}`); } const persistChatAttachments = Effect.fn("ws.assets.persistChatAttachments")(function* (input: { readonly threadId: ThreadId; readonly messageId: MessageId; readonly attachments: ReadonlyArray<{ readonly type: "image"; readonly name: string; readonly mimeType: string; readonly sizeBytes: number; readonly dataUrl: string; }>; }) { const config = yield* ServerConfig.ServerConfig; const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; return yield* Effect.forEach( input.attachments.map((attachment, index) => ({ attachment, index })), Effect.fn("ws.assets.persistChatAttachment")(function* ({ attachment, index }) { const parsed = parseBase64DataUrl(attachment.dataUrl); if (parsed === null || parsed.mimeType !== attachment.mimeType.toLowerCase()) { return yield* new PersistChatAttachmentsError({ message: `Attachment ${attachment.name} has an invalid image payload.`, }); } const bytes = yield* Effect.fromResult(Encoding.decodeBase64(parsed.base64)).pipe( Effect.mapError( (cause) => new PersistChatAttachmentsError({ message: `Attachment ${attachment.name} is not valid base64.`, cause, }), ), ); if (bytes.byteLength !== attachment.sizeBytes) { return yield* new PersistChatAttachmentsError({ message: `Attachment ${attachment.name} size does not match its payload.`, }); } const rawId = createDeterministicAttachmentId(input.threadId, `${input.messageId}:${index}`); if (rawId === null) { return yield* new PersistChatAttachmentsError({ message: "Could not allocate an attachment identifier.", }); } const persisted = { type: "image" as const, id: ChatAttachmentId.make(rawId), name: attachment.name, mimeType: attachment.mimeType, sizeBytes: attachment.sizeBytes, }; yield* fileSystem .writeFile(path.join(config.attachmentsDir, attachmentRelativePath(persisted)!), bytes) .pipe( Effect.mapError( (cause) => new PersistChatAttachmentsError({ message: `Could not persist attachment ${attachment.name}.`, cause, }), ), ); return persisted; }), { concurrency: 2 }, ); }); 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); } } const PROVIDER_STATUS_DEBOUNCE_MS = 200; const ServerWsRpcGroup = WsRpcGroup; // When a resuming client's cursor is more than this many events behind the // current head, skip the per-event catch-up replay and send a fresh shell // snapshot instead. Replaying each intervening event costs a shell refetch; // past this gap a single O(active-threads) snapshot is cheaper and bounded. // Matches the event store's default page size (DEFAULT_READ_FROM_SEQUENCE_LIMIT). const SHELL_RESUME_MAX_GAP = 1_000; // Row count alone does not bound replay memory: a few events with large tool // payloads can decode to gigabytes. Before replaying, sum the serialized // payload bytes of the range in SQL and reset with a snapshot past this budget. const ORCHESTRATION_REPLAY_PAYLOAD_BUDGET_BYTES = 8 * 1024 * 1024; 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 isClientSurface = Schema.is(ClientSurface); const isClientConnectionMethod = Schema.is(ClientConnectionMethod); const isClientDeviceType = Schema.is(ClientDeviceType); const isClientOs = Schema.is(ClientOs); const isClientWebDeployment = Schema.is(ClientWebDeployment); const MAX_CLIENT_APP_VERSION_LENGTH = 64; const MAX_CLIENT_BROWSER_LENGTH = 64; const MAX_CLIENT_DEVICE_MODEL_LENGTH = 80; export function hasCompatibleOrchestrationProtocol(url: URL): boolean { return ( url.searchParams.get(ORCHESTRATION_PROTOCOL_QUERY_PARAM) === String(ORCHESTRATION_PROTOCOL_VERSION) ); } // Optional client identity announced on the /ws upgrade URL next to wsTicket. // Lenient by design: absent or malformed values degrade to {} so a connection // never fails over attribution metadata. function readClientConnectionOrigin( request: HttpServerRequest.HttpServerRequest, ): OrchestrationClientOrigin { const url = HttpServerRequest.toURL(request); if (Option.isNone(url)) { return {}; } const surface = url.value.searchParams.get("clientSurface"); const appVersion = url.value.searchParams.get("clientAppVersion")?.trim() ?? ""; return { ...(isClientSurface(surface) ? { surface } : {}), ...(appVersion !== "" && appVersion.length <= MAX_CLIENT_APP_VERSION_LENGTH ? { appVersion } : {}), }; } // Client telemetry stays in this socket's RPC layer. It must not become a // server-global "current client" because several client types can connect at once. function readClientAnalyticsProps(request: HttpServerRequest.HttpServerRequest) { const url = HttpServerRequest.toURL(request); if (Option.isNone(url)) { return {}; } const surface = url.value.searchParams.get("clientSurface"); const appVersion = url.value.searchParams.get("clientAppVersion")?.trim() ?? ""; const deviceType = url.value.searchParams.get("clientDeviceType"); const os = url.value.searchParams.get("clientOs"); const webDeployment = url.value.searchParams.get("clientWebDeployment"); const browser = url.value.searchParams.get("clientBrowser")?.trim() ?? ""; const connectionMethod = url.value.searchParams.get("connectionMethod"); const rawOsMajorVersion = url.value.searchParams.get("clientOsMajorVersion") ?? ""; const osMajorVersion = Number(rawOsMajorVersion); const deviceModel = url.value.searchParams.get("clientDeviceModel")?.trim() ?? ""; const isMobile = surface === "mobile"; const hasOsMajorVersion = isMobile && rawOsMajorVersion !== "" && Number.isInteger(osMajorVersion) && osMajorVersion > 0; const hasDeviceModel = isMobile && deviceModel !== "" && deviceModel.length <= MAX_CLIENT_DEVICE_MODEL_LENGTH; return { ...(isClientSurface(surface) ? { surface } : {}), ...(appVersion !== "" && appVersion.length <= MAX_CLIENT_APP_VERSION_LENGTH ? { appVersion, clientAppVersion: appVersion }