import { EnvironmentHttpApi, ProviderDriverKind } from "@t3tools/contracts";import * as Cause from "effect/Cause";import * as Duration from "effect/Duration";import * as Deferred from "effect/Deferred";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Stream from "effect/Stream";import * as Schedule from "effect/Schedule";import { FetchHttpClient, HttpRouter, HttpServer } from "effect/unstable/http";import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder"; import * as BackgroundPolicy from "./background/BackgroundPolicy.ts";import * as HostPowerMonitor from "./background/HostPowerMonitor.ts";import * as ServerConfig from "./config.ts";import { otlpTracesProxyRouteLayer, assetRouteLayer, attachmentUploadRouteLayer, serverEnvironmentHttpApiLayer, staticAndDevRouteLayer, browserApiCorsLayer, httpCompressionLayer,} from "./http.ts";import { guardHttpResponseWriteErrors } from "./httpResponseErrorGuard.ts";import { fixPath } from "./os-jank.ts";import { websocketRpcRouteLayer } from "./ws.ts";import * as ExternalLauncher from "./process/externalLauncher.ts";import { pullRequestHttpApiLayer } from "./pullRequest/http.ts";import * as PullRequestProviderRegistry from "./pullRequest/PullRequestProviderRegistry.ts";import * as PullRequestService from "./pullRequest/PullRequestService.ts";import { layerConfig as SqlitePersistenceLayerLive } from "./persistence/Layers/Sqlite.ts";import * as ServerLifecycleEvents from "./serverLifecycleEvents.ts";import * as AnalyticsService from "./telemetry/AnalyticsService.ts";import * as ProviderEventIngestor from "./orchestration-v2/ProviderEventIngestor.ts";import * as ModelManifest from "./provider/ModelManifest.ts";import * as ProviderEventLoggers from "./provider/Layers/ProviderEventLoggers.ts";import * as OpenCodeRuntime from "./provider/opencodeRuntime.ts";import * as CheckpointDiffQuery from "./checkpointing/CheckpointDiffQuery.ts";import * as CheckpointStore from "./checkpointing/CheckpointStore.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 TextGeneration from "./textGeneration/TextGeneration.ts";import { ProviderInstanceRegistryHydrationLive } from "./provider/Layers/ProviderInstanceRegistryHydration.ts";import * as TerminalManager from "./terminal/Manager.ts";import * as McpHttpServer from "./mcp/McpHttpServer.ts";import * as McpSessionRegistry from "./mcp/McpSessionRegistry.ts";import * as PreviewAutomationBroker from "./mcp/PreviewAutomationBroker.ts";import * as PreviewManager from "./preview/Manager.ts";import * as PortScanner from "./preview/PortScanner.ts";import * as ProcessRunner from "./processRunner.ts";import * as GitManager from "./git/GitManager.ts";import * as EnvironmentTheme from "./environmentTheme.ts";import * as Keybindings from "./keybindings.ts";import * as ServerRuntimeStartup from "./serverRuntimeStartup.ts";import * as AgentAwarenessRelay from "./relay/AgentAwarenessRelay.ts";import { hasCloudPublicConfig } from "./cloud/publicConfig.ts";import { ProviderRegistryLive } from "./provider/Layers/ProviderRegistry.ts";import * as ServerSettings from "./serverSettings.ts";import * as ProjectEnrichmentService from "./project/ProjectEnrichmentService.ts";import * as NativeAppIconResolver from "./assets/NativeAppIconResolver.ts";import * as CodexResetCredit from "./provider/Layers/codexResetCredit.ts";import { AntigravityInstallation } from "./provider/AntigravityInstallation.ts";import { ProviderInstanceRegistry } from "./provider/Services/ProviderInstanceRegistry.ts";import { ProviderRegistry } from "./provider/Services/ProviderRegistry.ts";import { ProviderUsageLimitsIngestionLive } from "./provider/Layers/ProviderUsageLimitsIngestion.ts";import * as UsageLimitSources from "./usage/UsageLimitSources.ts";import * as ProjectFaviconResolver from "./project/ProjectFaviconResolver.ts";import * as T3ProjectFileLoader from "./project/T3ProjectFileLoader.ts";import * as RepositoryIdentityResolver from "./project/RepositoryIdentityResolver.ts";import * as WorkspaceEntries from "./workspace/WorkspaceEntries.ts";import * as WorkspaceFileSystem from "./workspace/WorkspaceFileSystem.ts";import * as WorkspacePaths from "./workspace/WorkspacePaths.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 VcsProvisioningService from "./vcs/VcsProvisioningService.ts";import * as VcsStatusBroadcaster from "./vcs/VcsStatusBroadcaster.ts";import * as GitWorkflowService from "./git/GitWorkflowService.ts";import * as ReviewService from "./review/ReviewService.ts";import * as SourceControlProviderRegistry from "./sourceControl/SourceControlProviderRegistry.ts";import * as SourceControlRateLimit from "./sourceControl/SourceControlRateLimit.ts";import * as SourceControlRepositoryService from "./sourceControl/SourceControlRepositoryService.ts";import { ObservabilityLive } from "./observability/Layers/Observability.ts";import * as ServerEnvironment from "./environment/ServerEnvironment.ts";import * as RemoteOpenTargets from "./environment/RemoteOpenTargets.ts";import { authHttpApiLayer, environmentAuthenticatedAuthLayer } from "./auth/http.ts";import * as ServerSecretStore from "./auth/ServerSecretStore.ts";import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts";import { connectHttpApiLayer, pendingServiceUpdateExists, reconcileDesiredCloudLink, releaseManagedTunnelOnShutdown,} from "./cloud/http.ts";import { serverRelayBrokerTracingLayer } from "./cloud/relayTracing.ts";import { shouldRetryCloudLink } from "./cloud/relayResponse.ts";import * as CloudManagedEndpointRuntime from "./cloud/ManagedEndpointRuntime.ts";import * as CloudCliTokenManager from "./cloud/CliTokenManager.ts";import * as CloudCliState from "./cloud/CliState.ts";import * as ServerSelfUpdate from "./cloud/selfUpdate.ts";import * as DesktopAppUpdate from "./desktopUpdate/DesktopAppUpdate.ts";import * as ServiceLauncherClient from "./cloud/serviceLauncherClient.ts";import * as ProcessDiagnostics from "./diagnostics/ProcessDiagnostics.ts";import * as ProcessResourceMonitor from "./diagnostics/ProcessResourceMonitor.ts";import * as TraceDiagnostics from "./diagnostics/TraceDiagnostics.ts";import * as DesktopTelemetryReceiver from "./resourceTelemetry/DesktopTelemetryReceiver.ts";import * as NativeTelemetryClient from "./resourceTelemetry/NativeTelemetryClient.ts";import * as ResourceAttribution from "./resourceTelemetry/ResourceAttribution.ts";import * as ResourceMonitorBinary from "./resourceTelemetry/ResourceMonitorBinary.ts";import * as ResourceTelemetry from "./resourceTelemetry/ResourceTelemetry.ts";import * as UsageService from "./usage/UsageService.ts";import { OrchestrationInfrastructureLayerLive } from "./orchestration/runtimeLayer.ts";import { OrchestrationV2ProductionLayerLive, ProjectSetupScriptRunnerLayerLive,} from "./orchestration-v2/runtimeLayer.ts";import * as ResourceCleanupService from "./orchestration-v2/ResourceCleanupService.ts";import * as ThreadSettlementService from "./orchestration-v2/ThreadSettlementService.ts";import * as RunFinalizationService from "./orchestration-v2/RunFinalizationService.ts";import * as ProjectionStoreV2 from "./orchestration-v2/ProjectionStore.ts";import { clearPersistedServerRuntimeState, makePersistedServerRuntimeState, persistServerRuntimeState,} from "./serverRuntimeState.ts";import { orchestrationHttpApiLayer } from "./orchestration-v2/http.ts";import { projectHttpApiLayer } from "./project/http.ts";import * as NetService from "@t3tools/shared/Net";import * as RelayClient from "@t3tools/shared/relayClient";import { disableTailscaleServe, ensureTailscaleServe } from "@t3tools/tailscale";import { forkParked, ServerActivation } from "./serverActivation.ts"; // MCP handoff thread IDs include escaped provenance and can exceed find-my-way's// 100-character default for one path segment.export const HTTP_ROUTER_CONFIG = { maxParamLength: 512,} as const; // Effect's default preemptive shutdown waits 20s before finalizing request scopes.// T3's primary transport is long-lived WebSocket RPC, whose Effect scope finalizer// already closes the websocket gracefully. Do not add an artificial drain before// those finalizers get a chance to run.const HTTP_PREEMPTIVE_SHUTDOWN_GRACE_MS = 0;const ResourceAttributionLayerLive = ResourceAttribution.layer;const ApplicationObservabilityLive = ObservabilityLive.pipe( Layer.provideMerge(ResourceAttributionLayerLive),); const PtyAdapterLive = Layer.unwrap( Effect.gen(function* () { if (typeof Bun !== "undefined") { const BunPtyAdapter = yield* Effect.promise(() => import("./terminal/BunPtyAdapter.ts")); return BunPtyAdapter.layer; } else { const NodePtyAdapter = yield* Effect.promise(() => import("./terminal/NodePtyAdapter.ts")); return NodePtyAdapter.layer; } }),); const ServerSettingsLayerLive = ServerSettings.layer.pipe( Layer.provide(ServerSecretStore.layer), Layer.provideMerge(SqlitePersistenceLayerLive),); const NativeTelemetryLayerLive = NativeTelemetryClient.layer.pipe( Layer.provide(ResourceMonitorBinary.layer),);const DesktopTelemetryReceiverLayerLive = DesktopTelemetryReceiver.layer.pipe( Layer.provideMerge(ServerSettingsLayerLive),); const ResourceTelemetryLayerLive = ResourceTelemetry.layer.pipe( Layer.provideMerge(NativeTelemetryLayerLive), Layer.provideMerge(DesktopTelemetryReceiverLayerLive),); const HostPowerMonitorLayerLive = HostPowerMonitor.layer.pipe( Layer.provide(DesktopTelemetryReceiverLayerLive),); // Reuses DesktopTelemetryReceiverLayerLive: a fresh receiver layer here// would open a second reader on the desktop telemetry fd.const DesktopAppUpdateLayerLive = DesktopAppUpdate.layer.pipe( Layer.provide(DesktopTelemetryReceiverLayerLive),); const BackgroundLayerLive = BackgroundPolicy.layer.pipe( Layer.provide(HostPowerMonitorLayerLive), Layer.provideMerge(ServerSettingsLayerLive),); const UsageLayerLive = UsageService.layer.pipe(Layer.provide(ServerSettingsLayerLive)); const ResourceDiagnosticsLayerLive = Layer.mergeAll( ResourceTelemetryLayerLive, ProcessDiagnostics.layer.pipe(Layer.provide(ResourceTelemetryLayerLive)), ProcessResourceMonitor.layer.pipe(Layer.provide(ResourceTelemetryLayerLive)),); const RelayClientLive = Layer.unwrap( Effect.gen(function* () { const config = yield* ServerConfig.ServerConfig; return RelayClient.layerCloudflared({ baseDir: config.baseDir }); }),); const HttpServerLive = Layer.unwrap( Effect.gen(function* () { const config = yield* ServerConfig.ServerConfig; if (typeof Bun !== "undefined") { const BunHttpServer = yield* Effect.promise( () => import("@effect/platform-bun/BunHttpServer"), ); return BunHttpServer.layer({ port: config.port, hostname: config.host ?? "127.0.0.1", gracefulShutdownTimeout: HTTP_PREEMPTIVE_SHUTDOWN_GRACE_MS, websocket: { // Negotiate permessage-deflate with clients that offer it; clients // that don't still get uncompressed frames on their connection. A // dedicated compressor keeps a per-connection sliding window // (context takeover) so the compression dictionary is shared across // server-to-client frames. Decompression uses the shared // decompressor: uWebSockets' dedicated decompressor path can abort // connections (close 1006) on valid DEFLATE input — see // https://github.com/uNetworking/uWebSockets.js/issues/633. perMessageDeflate: { compress: "dedicated", decompress: "shared", }, }, }); } else { const [NodeHttpServer, NodeHttp] = yield* Effect.all([ Effect.promise(() => import("@effect/platform-node/NodeHttpServer")), Effect.promise(() => import("node:http")), ]); return NodeHttpServer.layer(() => guardHttpResponseWriteErrors(NodeHttp.createServer()), { host: config.host ?? "127.0.0.1", port: config.port, gracefulShutdownTimeout: HTTP_PREEMPTIVE_SHUTDOWN_GRACE_MS, // Negotiate permessage-deflate with clients that offer it; clients // that don't still get uncompressed frames on their connection. // Context takeover stays enabled (ws default) so the compression // window is shared across frames — that also makes small frames cheap // to compress, so no size threshold is set (ws only honors // `threshold` when context takeover is disabled). websocket: { perMessageDeflate: true }, }); } }),); const PlatformServicesLive = Layer.unwrap( Effect.gen(function* () { if (typeof Bun !== "undefined") { const { layer } = yield* Effect.promise(() => import("@effect/platform-bun/BunServices")); return layer; } else { const { layer } = yield* Effect.promise(() => import("@effect/platform-node/NodeServices")); return layer; } }),); const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(SqlitePersistenceLayerLive)); const VcsDriverRegistryLayerLive = VcsDriverRegistry.layer.pipe( Layer.provide(VcsProjectConfig.layer),); const SourceControlProviderRegistryLayerLive = SourceControlProviderRegistry.layer.pipe( Layer.provide( Layer.mergeAll(AzureDevOpsCli.layer, BitbucketApi.layer, GitHubCli.layer, GitLabCli.layer), ), Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(VcsDriverRegistryLayerLive),); const PullRequestServiceLive = PullRequestService.layer.pipe( Layer.provide(PullRequestProviderRegistry.layer), Layer.provide(SourceControlProviderRegistryLayerLive), Layer.provide(SourceControlRateLimit.layer),); const GitManagerLayerLive = GitManager.layer.pipe( Layer.provideMerge(ProjectSetupScriptRunnerLayerLive), Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(TextGeneration.layer),); const GitLayerLive = Layer.empty.pipe( Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(GitVcsDriver.layer),); const GitWorkflowLayerLive = GitWorkflowService.layer.pipe( Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive),); const SourceControlRepositoryServiceLayerLive = SourceControlRepositoryService.layer.pipe( Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(SourceControlProviderRegistryLayerLive),); const ReviewLayerLive = ReviewService.layer.pipe( Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(VcsDriverRegistryLayerLive),); const VcsLayerLive = Layer.empty.pipe( Layer.provideMerge(VcsProjectConfig.layer), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(VcsProvisioningService.layer.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge( VcsStatusBroadcaster.layer.pipe( Layer.provide(GitWorkflowLayerLive), // Auto-pull reads the projected project row. The orchestration runtime // also consumes the broadcaster (run finalization), so the policy gets // its own snapshot-query build instead of the runtime-level one. Layer.provide( VcsStatusBroadcaster.autoPullPolicyLayer.pipe( Layer.provide(OrchestrationInfrastructureLayerLive), ), ), ), ),); const CheckpointStoreLayerLive = CheckpointStore.layer.pipe( Layer.provide(VcsDriverRegistryLayerLive),); const PortScannerLayerLive = PortScanner.layer.pipe(Layer.provide(ProcessRunner.layer)); const TerminalLayerLive = TerminalManager.layer.pipe( Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive),); const PreviewLayerLive = Layer.empty.pipe( Layer.provideMerge(PreviewManager.layer), Layer.provideMerge(PortScannerLayerLive),); const WorkspaceEntriesLayerLive = WorkspaceEntries.layer.pipe(Layer.provide(WorkspacePaths.layer)); const WorkspaceFileSystemLayerLive = WorkspaceFileSystem.layer.pipe( Layer.provide(WorkspacePaths.layer), Layer.provide(WorkspaceEntriesLayerLive),); const WorkspaceLayerLive = Layer.mergeAll( WorkspacePaths.layer, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive,); const ProjectFaviconResolverLayerLive = ProjectFaviconResolver.layer.pipe( Layer.provide(WorkspacePaths.layer), Layer.provide(T3ProjectFileLoader.layer),); const ServerEnvironmentLayerLive = ServerEnvironment.layer.pipe( Layer.provide(ServerSecretStore.layer),); const AuthLayerLive = EnvironmentAuth.layer.pipe( Layer.provideMerge(PersistenceLayerLive), Layer.provide(ServerEnvironmentLayerLive), Layer.provide(ServerSecretStore.layer),); const CloudManagedEndpointRuntimeLive = Layer.mergeAll( RelayClientLive, CloudManagedEndpointRuntime.layer.pipe( Layer.provide(ServerSecretStore.layer), Layer.provide(RelayClientLive), ),); const OrchestrationV2RuntimeLayerLive = OrchestrationV2ProductionLayerLive.pipe( Layer.provide(ProviderEventIngestor.analyticsLive), Layer.provide(CheckpointStoreLayerLive), Layer.provide(GitWorkflowLayerLive), Layer.provide(ResourceCleanupService.live), Layer.provide( RunFinalizationService.observerLive.pipe( Layer.provide(ProjectionStoreV2.layer), Layer.provide(PullRequestServiceLive), Layer.provide(OrchestrationInfrastructureLayerLive), ), ),); const OrchestrationApplicationLayerLive = CheckpointDiffQuery.layer.pipe( Layer.provideMerge(CheckpointStoreLayerLive), Layer.provideMerge(OrchestrationV2RuntimeLayerLive),); // Automatic thread settlement (#8600): a server-owned sweep evaluates// inactivity and merged pull requests, then settles through the orchestrator// so every client sees the same shelf.const ThreadSettlementWorkerLive = Layer.effectDiscard( ThreadSettlementService.make.pipe(Effect.flatMap((service) => service.start())),).pipe(Layer.provide(PullRequestServiceLive), Layer.provide(ProjectionStoreV2.layer)); const AntigravityInstallationRefreshLive = Layer.effectDiscard( Effect.gen(function* () { const installation = yield* AntigravityInstallation; const instances = yield* ProviderInstanceRegistry; const providers = yield* ProviderRegistry; yield* installation.changes.pipe( Stream.map((state) => state.installedVersion), Stream.changes, Stream.drop(1), Stream.runForEach(() => instances.listInstances.pipe( Effect.flatMap((entries) => Effect.forEach( entries.filter( (instance) => instance.driverKind === ProviderDriverKind.make("antigravity"), ), (instance) => providers.refreshInstance(instance.instanceId), { discard: true }, ), ), ), ), Effect.forkScoped, ); }),); const RuntimeCoreDependenciesBaseLive = Layer.mergeAll( AgentAwarenessRelay.layer, ThreadSettlementWorkerLive, // Subscribes to `account.rate-limits.updated` so usage bars track live // telemetry instead of waiting for the next status probe. ProviderUsageLimitsIngestionLive, AntigravityInstallationRefreshLive,).pipe( // Core Services Layer.provideMerge(OrchestrationApplicationLayerLive), Layer.provideMerge(ServerSettingsLayerLive), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive)), Layer.provideMerge(PersistenceLayerLive), // Both read a user-owned file out of the state directory and stream changes // to clients; neither depends on the other. Layer.provideMerge( Layer.mergeAll(Keybindings.layer, EnvironmentTheme.layer, UsageLimitSources.layer), ), Layer.provideMerge(ProviderRegistryLive), // The instance registry is the new routing keystone — text generation, // adapter lookup, and runtime ingestion all resolve `ProviderInstanceId` // through this layer. Built-in drivers come from `BUILT_IN_DRIVERS`; // `providerInstances` hydration merges `settings.providers.<kind>` // with explicit `providerInstances` entries on boot. Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(AntigravityInstallation.layer),); const RuntimeCoreDependenciesLive = RuntimeCoreDependenciesBaseLive.pipe( // Shared native/canonical NDJSON writers used by both the per-instance // V2 drivers and the orchestration runtime. Provide resource attribution so // the rewritten telemetry pipeline can account for logical NDJSON writes. // Provided once at the runtime level so every consumer sees the same // logger instances. // `ModelManifest.layer` is the legacy-model classification data, refreshed // from the repo's `model-manifest.json` on `main` and applied by the // Codex/Claude drivers. Layer.provideMerge( Layer.mergeAll(ProviderEventLoggers.layer, ModelManifest.layer, CodexResetCredit.layer), ), // `OpenCodeDriver.create()` yields `OpenCodeRuntime`; previously the old // `ProviderRegistryLive` pulled `OpenCodeRuntimeLive` in for itself, but // the rewritten registry reads snapshots off the instance registry and // no longer transitively provides it. Exposing it at the runtime level // keeps a single Live for all opencode consumers. Layer.provideMerge(OpenCodeRuntime.OpenCodeRuntimeLive), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectEnrichmentService.layer), Layer.provideMerge(Layer.mergeAll(NativeAppIconResolver.layer, ProjectFaviconResolverLayerLive)), Layer.provideMerge(RepositoryIdentityResolver.layer), Layer.provideMerge(ServerEnvironmentLayerLive), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(ServerSecretStore.layer), Layer.provideMerge(Lines 1–500 of 782. Load more
import { EnvironmentHttpApi, ProviderDriverKind } from "@t3tools/contracts"; import * as Cause from "effect/Cause"; import * as Duration from "effect/Duration"; import * as Deferred from "effect/Deferred"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; import * as Stream from "effect/Stream"; import * as Schedule from "effect/Schedule"; import { FetchHttpClient, HttpRouter, HttpServer } from "effect/unstable/http"; import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder"; import * as BackgroundPolicy from "./background/BackgroundPolicy.ts"; import * as HostPowerMonitor from "./background/HostPowerMonitor.ts"; import * as ServerConfig from "./config.ts"; import { otlpTracesProxyRouteLayer, assetRouteLayer, attachmentUploadRouteLayer, serverEnvironmentHttpApiLayer, staticAndDevRouteLayer, browserApiCorsLayer, httpCompressionLayer, } from "./http.ts"; import { guardHttpResponseWriteErrors } from "./httpResponseErrorGuard.ts"; import { fixPath } from "./os-jank.ts"; import { websocketRpcRouteLayer } from "./ws.ts"; import * as ExternalLauncher from "./process/externalLauncher.ts"; import { pullRequestHttpApiLayer } from "./pullRequest/http.ts"; import * as PullRequestProviderRegistry from "./pullRequest/PullRequestProviderRegistry.ts"; import * as PullRequestService from "./pullRequest/PullRequestService.ts"; import { layerConfig as SqlitePersistenceLayerLive } from "./persistence/Layers/Sqlite.ts"; import * as ServerLifecycleEvents from "./serverLifecycleEvents.ts"; import * as AnalyticsService from "./telemetry/AnalyticsService.ts"; import * as ProviderEventIngestor from "./orchestration-v2/ProviderEventIngestor.ts"; import * as ModelManifest from "./provider/ModelManifest.ts"; import * as ProviderEventLoggers from "./provider/Layers/ProviderEventLoggers.ts"; import * as OpenCodeRuntime from "./provider/opencodeRuntime.ts"; import * as CheckpointDiffQuery from "./checkpointing/CheckpointDiffQuery.ts"; import * as CheckpointStore from "./checkpointing/CheckpointStore.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 TextGeneration from "./textGeneration/TextGeneration.ts"; import { ProviderInstanceRegistryHydrationLive } from "./provider/Layers/ProviderInstanceRegistryHydration.ts"; import * as TerminalManager from "./terminal/Manager.ts"; import * as McpHttpServer from "./mcp/McpHttpServer.ts"; import * as McpSessionRegistry from "./mcp/McpSessionRegistry.ts"; import * as PreviewAutomationBroker from "./mcp/PreviewAutomationBroker.ts"; import * as PreviewManager from "./preview/Manager.ts"; import * as PortScanner from "./preview/PortScanner.ts"; import * as ProcessRunner from "./processRunner.ts"; import * as GitManager from "./git/GitManager.ts"; import * as EnvironmentTheme from "./environmentTheme.ts"; import * as Keybindings from "./keybindings.ts"; import * as ServerRuntimeStartup from "./serverRuntimeStartup.ts"; import * as AgentAwarenessRelay from "./relay/AgentAwarenessRelay.ts"; import { hasCloudPublicConfig } from "./cloud/publicConfig.ts"; import { ProviderRegistryLive } from "./provider/Layers/ProviderRegistry.ts"; import * as ServerSettings from "./serverSettings.ts"; import * as ProjectEnrichmentService from "./project/ProjectEnrichmentService.ts"; import * as NativeAppIconResolver from "./assets/NativeAppIconResolver.ts"; import * as CodexResetCredit from "./provider/Layers/codexResetCredit.ts"; import { AntigravityInstallation } from "./provider/AntigravityInstallation.ts"; import { ProviderInstanceRegistry } from "./provider/Services/ProviderInstanceRegistry.ts"; import { ProviderRegistry } from "./provider/Services/ProviderRegistry.ts"; import { ProviderUsageLimitsIngestionLive } from "./provider/Layers/ProviderUsageLimitsIngestion.ts"; import * as UsageLimitSources from "./usage/UsageLimitSources.ts"; import * as ProjectFaviconResolver from "./project/ProjectFaviconResolver.ts"; import * as T3ProjectFileLoader from "./project/T3ProjectFileLoader.ts"; import * as RepositoryIdentityResolver from "./project/RepositoryIdentityResolver.ts"; import * as WorkspaceEntries from "./workspace/WorkspaceEntries.ts"; import * as WorkspaceFileSystem from "./workspace/WorkspaceFileSystem.ts"; import * as WorkspacePaths from "./workspace/WorkspacePaths.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 VcsProvisioningService from "./vcs/VcsProvisioningService.ts"; import * as VcsStatusBroadcaster from "./vcs/VcsStatusBroadcaster.ts"; import * as GitWorkflowService from "./git/GitWorkflowService.ts"; import * as ReviewService from "./review/ReviewService.ts"; import * as SourceControlProviderRegistry from "./sourceControl/SourceControlProviderRegistry.ts"; import * as SourceControlRateLimit from "./sourceControl/SourceControlRateLimit.ts"; import * as SourceControlRepositoryService from "./sourceControl/SourceControlRepositoryService.ts"; import { ObservabilityLive } from "./observability/Layers/Observability.ts"; import * as ServerEnvironment from "./environment/ServerEnvironment.ts"; import * as RemoteOpenTargets from "./environment/RemoteOpenTargets.ts"; import { authHttpApiLayer, environmentAuthenticatedAuthLayer } from "./auth/http.ts"; import * as ServerSecretStore from "./auth/ServerSecretStore.ts"; import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts"; import { connectHttpApiLayer, pendingServiceUpdateExists, reconcileDesiredCloudLink, releaseManagedTunnelOnShutdown, } from "./cloud/http.ts"; import { serverRelayBrokerTracingLayer } from "./cloud/relayTracing.ts"; import { shouldRetryCloudLink } from "./cloud/relayResponse.ts"; import * as CloudManagedEndpointRuntime from "./cloud/ManagedEndpointRuntime.ts"; import * as CloudCliTokenManager from "./cloud/CliTokenManager.ts"; import * as CloudCliState from "./cloud/CliState.ts"; import * as ServerSelfUpdate from "./cloud/selfUpdate.ts"; import * as DesktopAppUpdate from "./desktopUpdate/DesktopAppUpdate.ts"; import * as ServiceLauncherClient from "./cloud/serviceLauncherClient.ts"; import * as ProcessDiagnostics from "./diagnostics/ProcessDiagnostics.ts"; import * as ProcessResourceMonitor from "./diagnostics/ProcessResourceMonitor.ts"; import * as TraceDiagnostics from "./diagnostics/TraceDiagnostics.ts"; import * as DesktopTelemetryReceiver from "./resourceTelemetry/DesktopTelemetryReceiver.ts"; import * as NativeTelemetryClient from "./resourceTelemetry/NativeTelemetryClient.ts"; import * as ResourceAttribution from "./resourceTelemetry/ResourceAttribution.ts"; import * as ResourceMonitorBinary from "./resourceTelemetry/ResourceMonitorBinary.ts"; import * as ResourceTelemetry from "./resourceTelemetry/ResourceTelemetry.ts"; import * as UsageService from "./usage/UsageService.ts"; import { OrchestrationInfrastructureLayerLive } from "./orchestration/runtimeLayer.ts"; import { OrchestrationV2ProductionLayerLive, ProjectSetupScriptRunnerLayerLive, } from "./orchestration-v2/runtimeLayer.ts"; import * as ResourceCleanupService from "./orchestration-v2/ResourceCleanupService.ts"; import * as ThreadSettlementService from "./orchestration-v2/ThreadSettlementService.ts"; import * as RunFinalizationService from "./orchestration-v2/RunFinalizationService.ts"; import * as ProjectionStoreV2 from "./orchestration-v2/ProjectionStore.ts"; import { clearPersistedServerRuntimeState, makePersistedServerRuntimeState, persistServerRuntimeState, } from "./serverRuntimeState.ts"; import { orchestrationHttpApiLayer } from "./orchestration-v2/http.ts"; import { projectHttpApiLayer } from "./project/http.ts"; import * as NetService from "@t3tools/shared/Net"; import * as RelayClient from "@t3tools/shared/relayClient"; import { disableTailscaleServe, ensureTailscaleServe } from "@t3tools/tailscale"; import { forkParked, ServerActivation } from "./serverActivation.ts"; // MCP handoff thread IDs include escaped provenance and can exceed find-my-way's // 100-character default for one path segment. export const HTTP_ROUTER_CONFIG = { maxParamLength: 512, } as const; // Effect's default preemptive shutdown waits 20s before finalizing request scopes. // T3's primary transport is long-lived WebSocket RPC, whose Effect scope finalizer // already closes the websocket gracefully. Do not add an artificial drain before // those finalizers get a chance to run. const HTTP_PREEMPTIVE_SHUTDOWN_GRACE_MS = 0; const ResourceAttributionLayerLive = ResourceAttribution.layer; const ApplicationObservabilityLive = ObservabilityLive.pipe( Layer.provideMerge(ResourceAttributionLayerLive), ); const PtyAdapterLive = Layer.unwrap( Effect.gen(function* () { if (typeof Bun !== "undefined") { const BunPtyAdapter = yield* Effect.promise(() => import("./terminal/BunPtyAdapter.ts")); return BunPtyAdapter.layer; } else { const NodePtyAdapter = yield* Effect.promise(() => import("./terminal/NodePtyAdapter.ts")); return NodePtyAdapter.layer; } }), ); const ServerSettingsLayerLive = ServerSettings.layer.pipe( Layer.provide(ServerSecretStore.layer), Layer.provideMerge(SqlitePersistenceLayerLive), ); const NativeTelemetryLayerLive = NativeTelemetryClient.layer.pipe( Layer.provide(ResourceMonitorBinary.layer), ); const DesktopTelemetryReceiverLayerLive = DesktopTelemetryReceiver.layer.pipe( Layer.provideMerge(ServerSettingsLayerLive), ); const ResourceTelemetryLayerLive = ResourceTelemetry.layer.pipe( Layer.provideMerge(NativeTelemetryLayerLive), Layer.provideMerge(DesktopTelemetryReceiverLayerLive), ); const HostPowerMonitorLayerLive = HostPowerMonitor.layer.pipe( Layer.provide(DesktopTelemetryReceiverLayerLive), ); // Reuses DesktopTelemetryReceiverLayerLive: a fresh receiver layer here // would open a second reader on the desktop telemetry fd. const DesktopAppUpdateLayerLive = DesktopAppUpdate.layer.pipe( Layer.provide(DesktopTelemetryReceiverLayerLive), ); const BackgroundLayerLive = BackgroundPolicy.layer.pipe( Layer.provide(HostPowerMonitorLayerLive), Layer.provideMerge(ServerSettingsLayerLive), ); const UsageLayerLive = UsageService.layer.pipe(Layer.provide(ServerSettingsLayerLive)); const ResourceDiagnosticsLayerLive = Layer.mergeAll( ResourceTelemetryLayerLive, ProcessDiagnostics.layer.pipe(Layer.provide(ResourceTelemetryLayerLive)), ProcessResourceMonitor.layer.pipe(Layer.provide(ResourceTelemetryLayerLive)), ); const RelayClientLive = Layer.unwrap( Effect.gen(function* () { const config = yield* ServerConfig.ServerConfig; return RelayClient.layerCloudflared({ baseDir: config.baseDir }); }), ); const HttpServerLive = Layer.unwrap( Effect.gen(function* () { const config = yield* ServerConfig.ServerConfig; if (typeof Bun !== "undefined") { const BunHttpServer = yield* Effect.promise( () => import("@effect/platform-bun/BunHttpServer"), ); return BunHttpServer.layer({ port: config.port, hostname: config.host ?? "127.0.0.1", gracefulShutdownTimeout: HTTP_PREEMPTIVE_SHUTDOWN_GRACE_MS, websocket: { // Negotiate permessage-deflate with clients that offer it; clients // that don't still get uncompressed frames on their connection. A // dedicated compressor keeps a per-connection sliding window // (context takeover) so the compression dictionary is shared across // server-to-client frames. Decompression uses the shared // decompressor: uWebSockets' dedicated decompressor path can abort // connections (close 1006) on valid DEFLATE input — see // https://github.com/uNetworking/uWebSockets.js/issues/633. perMessageDeflate: { compress: "dedicated", decompress: "shared", }, }, }); } else { const [NodeHttpServer, NodeHttp] = yield* Effect.all([ Effect.promise(() => import("@effect/platform-node/NodeHttpServer")), Effect.promise(() => import("node:http")), ]); return NodeHttpServer.layer(() => guardHttpResponseWriteErrors(NodeHttp.createServer()), { host: config.host ?? "127.0.0.1", port: config.port, gracefulShutdownTimeout: HTTP_PREEMPTIVE_SHUTDOWN_GRACE_MS, // Negotiate permessage-deflate with clients that offer it; clients // that don't still get uncompressed frames on their connection. // Context takeover stays enabled (ws default) so the compression // window is shared across frames — that also makes small frames cheap // to compress, so no size threshold is set (ws only honors // `threshold` when context takeover is disabled). websocket: { perMessageDeflate: true }, }); } }), ); const PlatformServicesLive = Layer.unwrap( Effect.gen(function* () { if (typeof Bun !== "undefined") { const { layer } = yield* Effect.promise(() => import("@effect/platform-bun/BunServices")); return layer; } else { const { layer } = yield* Effect.promise(() => import("@effect/platform-node/NodeServices")); return layer; } }), ); const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(SqlitePersistenceLayerLive)); const VcsDriverRegistryLayerLive = VcsDriverRegistry.layer.pipe( Layer.provide(VcsProjectConfig.layer), ); const SourceControlProviderRegistryLayerLive = SourceControlProviderRegistry.layer.pipe( Layer.provide( Layer.mergeAll(AzureDevOpsCli.layer, BitbucketApi.layer, GitHubCli.layer, GitLabCli.layer), ), Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(VcsDriverRegistryLayerLive), ); const PullRequestServiceLive = PullRequestService.layer.pipe( Layer.provide(PullRequestProviderRegistry.layer), Layer.provide(SourceControlProviderRegistryLayerLive), Layer.provide(SourceControlRateLimit.layer), ); const GitManagerLayerLive = GitManager.layer.pipe( Layer.provideMerge(ProjectSetupScriptRunnerLayerLive), Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(TextGeneration.layer), ); const GitLayerLive = Layer.empty.pipe( Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(GitVcsDriver.layer), ); const GitWorkflowLayerLive = GitWorkflowService.layer.pipe( Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive), ); const SourceControlRepositoryServiceLayerLive = SourceControlRepositoryService.layer.pipe( Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(SourceControlProviderRegistryLayerLive), ); const ReviewLayerLive = ReviewService.layer.pipe( Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(VcsDriverRegistryLayerLive), ); const VcsLayerLive = Layer.empty.pipe( Layer.provideMerge(VcsProjectConfig.layer), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(VcsProvisioningService.layer.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge( VcsStatusBroadcaster.layer.pipe( Layer.provide(GitWorkflowLayerLive), // Auto-pull reads the projected project row. The orchestration runtime // also consumes the broadcaster (run finalization), so the policy gets // its own snapshot-query build instead of the runtime-level one. Layer.provide( VcsStatusBroadcaster.autoPullPolicyLayer.pipe( Layer.provide(OrchestrationInfrastructureLayerLive), ), ), ), ), ); const CheckpointStoreLayerLive = CheckpointStore.layer.pipe( Layer.provide(VcsDriverRegistryLayerLive), ); const PortScannerLayerLive = PortScanner.layer.pipe(Layer.provide(ProcessRunner.layer)); const TerminalLayerLive = TerminalManager.layer.pipe( Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive), ); const PreviewLayerLive = Layer.empty.pipe( Layer.provideMerge(PreviewManager.layer), Layer.provideMerge(PortScannerLayerLive), ); const WorkspaceEntriesLayerLive = WorkspaceEntries.layer.pipe(Layer.provide(WorkspacePaths.layer)); const WorkspaceFileSystemLayerLive = WorkspaceFileSystem.layer.pipe( Layer.provide(WorkspacePaths.layer), Layer.provide(WorkspaceEntriesLayerLive), ); const WorkspaceLayerLive = Layer.mergeAll( WorkspacePaths.layer, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive, ); const ProjectFaviconResolverLayerLive = ProjectFaviconResolver.layer.pipe( Layer.provide(WorkspacePaths.layer), Layer.provide(T3ProjectFileLoader.layer), ); const ServerEnvironmentLayerLive = ServerEnvironment.layer.pipe( Layer.provide(ServerSecretStore.layer), ); const AuthLayerLive = EnvironmentAuth.layer.pipe( Layer.provideMerge(PersistenceLayerLive), Layer.provide(ServerEnvironmentLayerLive), Layer.provide(ServerSecretStore.layer), ); const CloudManagedEndpointRuntimeLive = Layer.mergeAll( RelayClientLive, CloudManagedEndpointRuntime.layer.pipe( Layer.provide(ServerSecretStore.layer), Layer.provide(RelayClientLive), ), ); const OrchestrationV2RuntimeLayerLive = OrchestrationV2ProductionLayerLive.pipe( Layer.provide(ProviderEventIngestor.analyticsLive), Layer.provide(CheckpointStoreLayerLive), Layer.provide(GitWorkflowLayerLive), Layer.provide(ResourceCleanupService.live), Layer.provide( RunFinalizationService.observerLive.pipe( Layer.provide(ProjectionStoreV2.layer), Layer.provide(PullRequestServiceLive), Layer.provide(OrchestrationInfrastructureLayerLive), ), ), ); const OrchestrationApplicationLayerLive = CheckpointDiffQuery.layer.pipe( Layer.provideMerge(CheckpointStoreLayerLive), Layer.provideMerge(OrchestrationV2RuntimeLayerLive), ); // Automatic thread settlement (#8600): a server-owned sweep evaluates // inactivity and merged pull requests, then settles through the orchestrator // so every client sees the same shelf. const ThreadSettlementWorkerLive = Layer.effectDiscard( ThreadSettlementService.make.pipe(Effect.flatMap((service) => service.start())), ).pipe(Layer.provide(PullRequestServiceLive), Layer.provide(ProjectionStoreV2.layer)); const AntigravityInstallationRefreshLive = Layer.effectDiscard( Effect.gen(function* () { const installation = yield* AntigravityInstallation; const instances = yield* ProviderInstanceRegistry; const providers = yield* ProviderRegistry; yield* installation.changes.pipe( Stream.map((state) => state.installedVersion), Stream.changes, Stream.drop(1), Stream.runForEach(() => instances.listInstances.pipe( Effect.flatMap((entries) => Effect.forEach( entries.filter( (instance) => instance.driverKind === ProviderDriverKind.make("antigravity"), ), (instance) => providers.refreshInstance(instance.instanceId), { discard: true }, ), ), ), ), Effect.forkScoped, ); }), ); const RuntimeCoreDependenciesBaseLive = Layer.mergeAll( AgentAwarenessRelay.layer, ThreadSettlementWorkerLive, // Subscribes to `account.rate-limits.updated` so usage bars track live // telemetry instead of waiting for the next status probe. ProviderUsageLimitsIngestionLive, AntigravityInstallationRefreshLive, ).pipe( // Core Services Layer.provideMerge(OrchestrationApplicationLayerLive), Layer.provideMerge(ServerSettingsLayerLive), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive)), Layer.provideMerge(PersistenceLayerLive), // Both read a user-owned file out of the state directory and stream changes // to clients; neither depends on the other. Layer.provideMerge( Layer.mergeAll(Keybindings.layer, EnvironmentTheme.layer, UsageLimitSources.layer), ), Layer.provideMerge(ProviderRegistryLive), // The instance registry is the new routing keystone — text generation, // adapter lookup, and runtime ingestion all resolve `ProviderInstanceId` // through this layer. Built-in drivers come from `BUILT_IN_DRIVERS`; // `providerInstances` hydration merges `settings.providers.<kind>` // with explicit `providerInstances` entries on boot. Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(AntigravityInstallation.layer), ); const RuntimeCoreDependenciesLive = RuntimeCoreDependenciesBaseLive.pipe( // Shared native/canonical NDJSON writers used by both the per-instance // V2 drivers and the orchestration runtime. Provide resource attribution so // the rewritten telemetry pipeline can account for logical NDJSON writes. // Provided once at the runtime level so every consumer sees the same // logger instances. // `ModelManifest.layer` is the legacy-model classification data, refreshed // from the repo's `model-manifest.json` on `main` and applied by the // Codex/Claude drivers. Layer.provideMerge( Layer.mergeAll(ProviderEventLoggers.layer, ModelManifest.layer, CodexResetCredit.layer), ), // `OpenCodeDriver.create()` yields `OpenCodeRuntime`; previously the old // `ProviderRegistryLive` pulled `OpenCodeRuntimeLive` in for itself, but // the rewritten registry reads snapshots off the instance registry and // no longer transitively provides it. Exposing it at the runtime level // keeps a single Live for all opencode consumers. Layer.provideMerge(OpenCodeRuntime.OpenCodeRuntimeLive), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectEnrichmentService.layer), Layer.provideMerge(Layer.mergeAll(NativeAppIconResolver.layer, ProjectFaviconResolverLayerLive)), Layer.provideMerge(RepositoryIdentityResolver.layer), Layer.provideMerge(ServerEnvironmentLayerLive), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(ServerSecretStore.layer), Layer.provideMerge(