diff --git a/apps/desktop/scripts/electron-launcher.mjs b/apps/desktop/scripts/electron-launcher.mjs index 496a8a27a7b6..ba852974ed3e 100644 --- a/apps/desktop/scripts/electron-launcher.mjs +++ b/apps/desktop/scripts/electron-launcher.mjs @@ -15,8 +15,8 @@ const repoRoot = NodePath.resolve(desktopDir, "..", ".."); const devBundleIdSuffix = NodePath.basename(repoRoot) .toLowerCase() .replaceAll(/[^a-z0-9]+/g, ""); -export const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)"; -export const APP_BUNDLE_ID = isDevelopment +const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)"; +const APP_BUNDLE_ID = isDevelopment ? `com.t3tools.t3code.dev.${devBundleIdSuffix || "local"}` : "com.t3tools.t3code"; const APP_PROTOCOL_SCHEMES = isDevelopment ? ["t3code-dev"] : ["t3code"]; @@ -387,7 +387,7 @@ function resolveLinuxSandboxArgs(electronBinaryPath) { return ["--no-sandbox"]; } -export function resolveElectronPath() { +function resolveElectronPath() { const electronBinaryPath = resolveElectronBinaryPath(); if (hostPlatform !== "darwin") { diff --git a/apps/desktop/src/app/DesktopAppActivation.ts b/apps/desktop/src/app/DesktopAppActivation.ts index f63fdffedaef..78f9b5bbe177 100644 --- a/apps/desktop/src/app/DesktopAppActivation.ts +++ b/apps/desktop/src/app/DesktopAppActivation.ts @@ -213,6 +213,7 @@ export class DesktopAppActivation extends Context.Service< const { logWarning } = makeComponentLogger("desktop-app-activation"); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const desktopEnvironment = yield* DesktopEnvironment.DesktopEnvironment; const desktopWindow = yield* DesktopWindow.DesktopWindow; diff --git a/apps/desktop/src/app/DesktopAppIdentity.ts b/apps/desktop/src/app/DesktopAppIdentity.ts index c5adb8574a53..3a6957d9fdb0 100644 --- a/apps/desktop/src/app/DesktopAppIdentity.ts +++ b/apps/desktop/src/app/DesktopAppIdentity.ts @@ -66,6 +66,7 @@ export const resolveUserDataPath = Effect.gen(function* () { : environment.path.join(environment.appDataDirectory, environment.userDataDirName); }).pipe(Effect.withSpan("desktop.appIdentity.resolveUserDataPath")); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const assets = yield* DesktopAssets.DesktopAssets; const electronApp = yield* ElectronApp.ElectronApp; diff --git a/apps/desktop/src/app/DesktopAssets.ts b/apps/desktop/src/app/DesktopAssets.ts index f1c6f1bb8f1f..d9c44b6e52e8 100644 --- a/apps/desktop/src/app/DesktopAssets.ts +++ b/apps/desktop/src/app/DesktopAssets.ts @@ -119,6 +119,7 @@ const resolveIconPath = Effect.fn("desktop.assets.resolveIconPath")(function* ( return yield* resolveResourcePath(`icon.${ext}`); }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const context = yield* Effect.context< FileSystem.FileSystem | DesktopEnvironment.DesktopEnvironment diff --git a/apps/desktop/src/app/DesktopClerk.ts b/apps/desktop/src/app/DesktopClerk.ts index d3c99e5e1d24..00df9951fd1e 100644 --- a/apps/desktop/src/app/DesktopClerk.ts +++ b/apps/desktop/src/app/DesktopClerk.ts @@ -83,6 +83,7 @@ function createDesktopClerkBridge(stateDir: string, isDevelopment: boolean) { }); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const electronApp = yield* ElectronApp.ElectronApp; diff --git a/apps/desktop/src/app/DesktopConnectionCatalogStore.ts b/apps/desktop/src/app/DesktopConnectionCatalogStore.ts index 5ec2edb595ff..17505aad5569 100644 --- a/apps/desktop/src/app/DesktopConnectionCatalogStore.ts +++ b/apps/desktop/src/app/DesktopConnectionCatalogStore.ts @@ -375,6 +375,7 @@ const migrateSavedEnvironmentRecords = Effect.fn( }; }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/desktop/src/app/DesktopLifecycle.ts b/apps/desktop/src/app/DesktopLifecycle.ts index 0a0cc6dca933..8e5b88565185 100644 --- a/apps/desktop/src/app/DesktopLifecycle.ts +++ b/apps/desktop/src/app/DesktopLifecycle.ts @@ -159,6 +159,7 @@ function quitFromSignal( ); } +/** @public Service construction is part of the module API alongside layer. */ export const make = DesktopLifecycle.of({ relaunch: Effect.fn("desktop.lifecycle.relaunch")(function* (reason) { const electronApp = yield* ElectronApp.ElectronApp; diff --git a/apps/desktop/src/app/DesktopLinuxUrlHandler.ts b/apps/desktop/src/app/DesktopLinuxUrlHandler.ts index e531a54dfce6..9337dc90821a 100644 --- a/apps/desktop/src/app/DesktopLinuxUrlHandler.ts +++ b/apps/desktop/src/app/DesktopLinuxUrlHandler.ts @@ -20,7 +20,7 @@ import { makeComponentLogger } from "./DesktopObservability.ts"; // our own handler entry pointing at the current AppImage and claim the // scheme default via xdg-mime, exactly what the file manager's "set as // default" checkbox would record in mimeapps.list. -export const URL_HANDLER_DESKTOP_ENTRY_NAME = "t3code-url-handler.desktop"; +const URL_HANDLER_DESKTOP_ENTRY_NAME = "t3code-url-handler.desktop"; const { logInfo, logWarning } = makeComponentLogger("desktop-linux-url-handler"); @@ -92,6 +92,7 @@ export class DesktopLinuxUrlHandler extends Context.Service< } >()("@t3tools/desktop/app/DesktopLinuxUrlHandler") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/desktop/src/app/DesktopPreReadyPlatform.ts b/apps/desktop/src/app/DesktopPreReadyPlatform.ts index 718f54115065..987021845f86 100644 --- a/apps/desktop/src/app/DesktopPreReadyPlatform.ts +++ b/apps/desktop/src/app/DesktopPreReadyPlatform.ts @@ -46,6 +46,7 @@ export class DesktopPreReadyElectronOptions extends Context.Service< } >()("@t3tools/desktop/app/DesktopPreReadyPlatform/DesktopPreReadyElectronOptions") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const platform = yield* HostProcessPlatform; return yield* Effect.sync((): DesktopPreReadyElectronOptions["Service"] => { diff --git a/apps/desktop/src/backend/DesktopBackendConfiguration.ts b/apps/desktop/src/backend/DesktopBackendConfiguration.ts index 7a8dc8334cf1..1b56dd41ecf3 100644 --- a/apps/desktop/src/backend/DesktopBackendConfiguration.ts +++ b/apps/desktop/src/backend/DesktopBackendConfiguration.ts @@ -737,6 +737,7 @@ const resolveWslStartConfig = Effect.fn("desktop.backendConfiguration.resolveWsl } satisfies DesktopBackendManager.DesktopBackendStartConfig; }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/desktop/src/backend/DesktopLocalEnvironmentAuth.ts b/apps/desktop/src/backend/DesktopLocalEnvironmentAuth.ts index 201492f0e4c1..ca3160d01196 100644 --- a/apps/desktop/src/backend/DesktopLocalEnvironmentAuth.ts +++ b/apps/desktop/src/backend/DesktopLocalEnvironmentAuth.ts @@ -42,6 +42,7 @@ export class DesktopLocalEnvironmentAuth extends Context.Service< } >()("@t3tools/desktop/backend/DesktopLocalEnvironmentAuth") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const pool = yield* DesktopBackendPool.DesktopBackendPool; const httpClient = yield* HttpClient.HttpClient; diff --git a/apps/desktop/src/backend/DesktopNetworkInterfaces.ts b/apps/desktop/src/backend/DesktopNetworkInterfaces.ts index 43f634c44917..d83603240c76 100644 --- a/apps/desktop/src/backend/DesktopNetworkInterfaces.ts +++ b/apps/desktop/src/backend/DesktopNetworkInterfaces.ts @@ -39,6 +39,7 @@ export class DesktopNetworkInterfaces extends Context.Service< } >()("@t3tools/desktop/backend/DesktopNetworkInterfaces") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const platform = yield* HostProcessPlatform; return DesktopNetworkInterfaces.of({ diff --git a/apps/desktop/src/backend/DesktopServerExposure.ts b/apps/desktop/src/backend/DesktopServerExposure.ts index 24c24c15a00f..e3932ee2fed2 100644 --- a/apps/desktop/src/backend/DesktopServerExposure.ts +++ b/apps/desktop/src/backend/DesktopServerExposure.ts @@ -27,7 +27,7 @@ import { resolveTailscaleAdvertisedEndpoints } from "./tailscaleEndpointProvider const TAILSCALE_STATUS_CACHE_TTL = Duration.seconds(60); -export const DESKTOP_LOOPBACK_HOST = "127.0.0.1"; +const DESKTOP_LOOPBACK_HOST = "127.0.0.1"; const DESKTOP_LAN_BIND_HOST = "0.0.0.0"; interface ResolvedDesktopServerExposure { @@ -411,6 +411,7 @@ const requiresBackendRelaunch = (previous: RuntimeState, next: RuntimeState): bo previous.bindHost !== next.bindHost || previous.localHttpUrl !== next.localHttpUrl; +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const config = yield* DesktopConfig.DesktopConfig; const networkInterfaces = yield* DesktopNetworkInterfaces.DesktopNetworkInterfaces; diff --git a/apps/desktop/src/backend/tailscaleEndpointProvider.ts b/apps/desktop/src/backend/tailscaleEndpointProvider.ts index 0b48adc308c3..5a5a20780a65 100644 --- a/apps/desktop/src/backend/tailscaleEndpointProvider.ts +++ b/apps/desktop/src/backend/tailscaleEndpointProvider.ts @@ -14,7 +14,7 @@ import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawne import type { NetworkInterfaces } from "./DesktopNetworkInterfaces.ts"; -export { isTailscaleIpv4Address, parseTailscaleMagicDnsName } from "@t3tools/tailscale"; +export { parseTailscaleMagicDnsName } from "@t3tools/tailscale"; const TAILSCALE_ENDPOINT_PROVIDER: AdvertisedEndpointProvider = { id: "tailscale", diff --git a/apps/desktop/src/electron/ElectronApp.ts b/apps/desktop/src/electron/ElectronApp.ts index 5a6f16ae89fd..903fd4fb05aa 100644 --- a/apps/desktop/src/electron/ElectronApp.ts +++ b/apps/desktop/src/electron/ElectronApp.ts @@ -98,6 +98,7 @@ const addScopedAppListener = >( }), ).pipe(Effect.asVoid); +/** @public Service construction is part of the module API alongside layer. */ export const make = ElectronApp.of({ metadata: Effect.gen(function* () { const appVersion = yield* Effect.try({ diff --git a/apps/desktop/src/electron/ElectronDialog.ts b/apps/desktop/src/electron/ElectronDialog.ts index 30ca73a5e143..943fdb7213cc 100644 --- a/apps/desktop/src/electron/ElectronDialog.ts +++ b/apps/desktop/src/electron/ElectronDialog.ts @@ -102,6 +102,7 @@ export class ElectronDialog extends Context.Service< } >()("@t3tools/desktop/electron/ElectronDialog") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = ElectronDialog.of({ pickFolder: Effect.fn("desktop.electron.dialog.pickFolder")(function* (input) { const ownerWindowId = Option.match(input.owner, { diff --git a/apps/desktop/src/electron/ElectronMenu.ts b/apps/desktop/src/electron/ElectronMenu.ts index b241619cd296..0cc6d893588d 100644 --- a/apps/desktop/src/electron/ElectronMenu.ts +++ b/apps/desktop/src/electron/ElectronMenu.ts @@ -110,6 +110,7 @@ const normalizePosition = ( Option.map(({ x, y }) => ({ x: Math.floor(x * zoomFactor), y: Math.floor(y * zoomFactor) })), ); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const platform = yield* HostProcessPlatform; let destructiveMenuIconCache: Option.Option | undefined; diff --git a/apps/desktop/src/electron/ElectronPowerMonitor.ts b/apps/desktop/src/electron/ElectronPowerMonitor.ts index ad322a573fba..ef5808dfe161 100644 --- a/apps/desktop/src/electron/ElectronPowerMonitor.ts +++ b/apps/desktop/src/electron/ElectronPowerMonitor.ts @@ -75,6 +75,7 @@ const onSpeedLimitChange: ElectronPowerMonitor["Service"]["onSpeedLimitChange"] ).pipe(Effect.asVoid); }; +/** @public Service construction is part of the module API alongside layer. */ export const make = ElectronPowerMonitor.of({ isOnBatteryPower: Effect.sync(() => Electron.powerMonitor.isOnBatteryPower()), getSystemIdleTime: Effect.sync(() => Electron.powerMonitor.getSystemIdleTime()), diff --git a/apps/desktop/src/electron/ElectronProtocol.ts b/apps/desktop/src/electron/ElectronProtocol.ts index fabd598d7ffa..d454a6d7619b 100644 --- a/apps/desktop/src/electron/ElectronProtocol.ts +++ b/apps/desktop/src/electron/ElectronProtocol.ts @@ -9,14 +9,14 @@ import * as Scope from "effect/Scope"; import * as Electron from "electron"; export const DESKTOP_HOST = "app"; -export const DESKTOP_PRODUCTION_SCHEME = "t3code"; -export const DESKTOP_DEVELOPMENT_SCHEME = "t3code-dev"; +const DESKTOP_PRODUCTION_SCHEME = "t3code"; +const DESKTOP_DEVELOPMENT_SCHEME = "t3code-dev"; export function getDesktopScheme(isDevelopment: boolean): string { return isDevelopment ? DESKTOP_DEVELOPMENT_SCHEME : DESKTOP_PRODUCTION_SCHEME; } -export function getDesktopOrigin(isDevelopment: boolean): string { +function getDesktopOrigin(isDevelopment: boolean): string { return `${getDesktopScheme(isDevelopment)}://${DESKTOP_HOST}`; } @@ -109,7 +109,7 @@ function withContentSecurityPolicy(response: Response, policy: string): Response /** * Must run synchronously during process bootstrap, before Electron emits `ready`. */ -export function registerDesktopSchemePrivilegesSync(): void { +function registerDesktopSchemePrivilegesSync(): void { Electron.protocol.registerSchemesAsPrivileged([ { scheme: DESKTOP_PRODUCTION_SCHEME, @@ -205,6 +205,7 @@ async function fetchWithTransientRetry(url: string, init: RequestInit): Promise< throw lastError; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const registered = yield* Ref.make(false); diff --git a/apps/desktop/src/electron/ElectronSafeStorage.ts b/apps/desktop/src/electron/ElectronSafeStorage.ts index b9dab7105fb8..bf969c455bd1 100644 --- a/apps/desktop/src/electron/ElectronSafeStorage.ts +++ b/apps/desktop/src/electron/ElectronSafeStorage.ts @@ -50,7 +50,6 @@ export const ElectronSafeStorageError = Schema.Union([ ElectronSafeStorageDecryptError, ]); export type ElectronSafeStorageError = typeof ElectronSafeStorageError.Type; -export const isElectronSafeStorageError = Schema.is(ElectronSafeStorageError); export class ElectronSafeStorage extends Context.Service< ElectronSafeStorage, @@ -66,6 +65,7 @@ export class ElectronSafeStorage extends Context.Service< } >()("@t3tools/desktop/electron/ElectronSafeStorage") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const platform = yield* HostProcessPlatform; diff --git a/apps/desktop/src/electron/ElectronShell.ts b/apps/desktop/src/electron/ElectronShell.ts index 0ac4f8f9cc6a..9b1c7973daaf 100644 --- a/apps/desktop/src/electron/ElectronShell.ts +++ b/apps/desktop/src/electron/ElectronShell.ts @@ -67,6 +67,7 @@ export class ElectronShell extends Context.Service< } >()("@t3tools/desktop/electron/ElectronShell") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = ElectronShell.of({ openExternal: (rawUrl) => Option.match(parseSafeExternalUrl(rawUrl), { diff --git a/apps/desktop/src/electron/ElectronTheme.ts b/apps/desktop/src/electron/ElectronTheme.ts index 24b2d856b9d2..11348839a314 100644 --- a/apps/desktop/src/electron/ElectronTheme.ts +++ b/apps/desktop/src/electron/ElectronTheme.ts @@ -28,6 +28,7 @@ export class ElectronTheme extends Context.Service< } >()("@t3tools/desktop/electron/ElectronTheme") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = ElectronTheme.of({ shouldUseDarkColors: Effect.sync(() => Electron.nativeTheme.shouldUseDarkColors), setSource: (theme) => diff --git a/apps/desktop/src/electron/ElectronUpdater.ts b/apps/desktop/src/electron/ElectronUpdater.ts index 8e044de65ad6..05eb09705c67 100644 --- a/apps/desktop/src/electron/ElectronUpdater.ts +++ b/apps/desktop/src/electron/ElectronUpdater.ts @@ -80,6 +80,7 @@ export class ElectronUpdater extends Context.Service< } >()("@t3tools/desktop/electron/ElectronUpdater") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = ElectronUpdater.of({ setFeedURL: (options) => Effect.suspend(() => { diff --git a/apps/desktop/src/electron/ElectronWindow.ts b/apps/desktop/src/electron/ElectronWindow.ts index 9234399191cf..8238911a7277 100644 --- a/apps/desktop/src/electron/ElectronWindow.ts +++ b/apps/desktop/src/electron/ElectronWindow.ts @@ -95,6 +95,7 @@ export class ElectronWindow extends Context.Service< } >()("@t3tools/desktop/electron/ElectronWindow") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const platform = yield* HostProcessPlatform; const mainWindowRef = yield* Ref.make>(Option.none()); diff --git a/apps/desktop/src/preview/BrowserImport/BrowserImport.ts b/apps/desktop/src/preview/BrowserImport/BrowserImport.ts index 386b3ef6f813..8db4c497b107 100644 --- a/apps/desktop/src/preview/BrowserImport/BrowserImport.ts +++ b/apps/desktop/src/preview/BrowserImport/BrowserImport.ts @@ -166,6 +166,7 @@ export const writeCookies = Effect.fn("BrowserImport.writeCookies")(function* ( return { imported, skipped, skippedDomains: [...skippedDomains].slice(0, 20) }; }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* BrowserImportMake() { const browserSession = yield* BrowserSession.BrowserSession; const platform = yield* HostProcessPlatform; diff --git a/apps/desktop/src/preview/BrowserSession.ts b/apps/desktop/src/preview/BrowserSession.ts index 7ff879852283..fde55e07e9f6 100644 --- a/apps/desktop/src/preview/BrowserSession.ts +++ b/apps/desktop/src/preview/BrowserSession.ts @@ -159,6 +159,7 @@ const encodeScopeForDigest = (scope: string): Uint8Array => ), ); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* BrowserSessionMake() { const crypto = yield* Crypto.Crypto; const sessionsRef = yield* SynchronizedRef.make>(new Map()); diff --git a/apps/desktop/src/preview/FaviconCapture.ts b/apps/desktop/src/preview/FaviconCapture.ts index c7266282268e..e184ab905666 100644 --- a/apps/desktop/src/preview/FaviconCapture.ts +++ b/apps/desktop/src/preview/FaviconCapture.ts @@ -2,7 +2,7 @@ import { FAVICON_DATA_URL_MAX_LENGTH } from "@t3tools/contracts"; export const MAX_FAVICON_RESPONSE_BYTES = 100_000; export const MAX_FAVICON_CANDIDATES = 8; -export const MAX_FAVICON_HTTP_URL_LENGTH = 2_048; +const MAX_FAVICON_HTTP_URL_LENGTH = 2_048; const MAX_FAVICON_CANDIDATE_INPUT_UNITS = 262_144; const MIN_FAVICON_CANDIDATE_INPUT_UNITS = 256; diff --git a/apps/desktop/src/preview/Manager.ts b/apps/desktop/src/preview/Manager.ts index 900ba5fe983c..118d14ab8096 100644 --- a/apps/desktop/src/preview/Manager.ts +++ b/apps/desktop/src/preview/Manager.ts @@ -153,7 +153,7 @@ const DEFAULT_ANNOTATION_THEME: DesktopPreviewAnnotationTheme = { fontMono: "ui-monospace, monospace", }; -export const buildPreviewPictureInPictureDataUrl = (): string => { +const buildPreviewPictureInPictureDataUrl = (): string => { const html = ` @@ -4271,7 +4271,7 @@ export class PreviewOperationError extends Schema.TaggedErrorClass()( "PreviewArtifactPathOutsideDirectoryError", @@ -4472,14 +4472,11 @@ export const PreviewManagerError = Schema.Union([ ]); export type PreviewManagerError = typeof PreviewManagerError.Type; -export const isPreviewManagerError = Schema.is(PreviewManagerError); -export const isPreviewAutomationControlInterruptedError = Schema.is( +const isPreviewAutomationControlInterruptedError = Schema.is( PreviewAutomationControlInterruptedError, ); -export const isPreviewAutomationEvaluationError = Schema.is(PreviewAutomationEvaluationError); -export const isPreviewAutomationInvalidSelectorError = Schema.is( - PreviewAutomationInvalidSelectorError, -); +const isPreviewAutomationEvaluationError = Schema.is(PreviewAutomationEvaluationError); +const isPreviewAutomationInvalidSelectorError = Schema.is(PreviewAutomationInvalidSelectorError); export class PreviewManager extends Context.Service< PreviewManager, @@ -4592,6 +4589,7 @@ export class PreviewManager extends Context.Service< } >()("@t3tools/desktop/preview/Manager/PreviewManager") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* PreviewManagerMake() { const environment = yield* DesktopEnvironment.DesktopEnvironment; const browserSession = yield* BrowserSession.BrowserSession; diff --git a/apps/desktop/src/settings/DesktopAppSettings.ts b/apps/desktop/src/settings/DesktopAppSettings.ts index aefc67525531..c07689f069b9 100644 --- a/apps/desktop/src/settings/DesktopAppSettings.ts +++ b/apps/desktop/src/settings/DesktopAppSettings.ts @@ -55,7 +55,7 @@ export interface DesktopSettingsChange { readonly changed: boolean; } -export const DEFAULT_TAILSCALE_SERVE_PORT = 443; +const DEFAULT_TAILSCALE_SERVE_PORT = 443; const MIN_MAIN_WINDOW_SIZE = { width: 840, height: 620, @@ -450,6 +450,7 @@ const writeSettings = Effect.fn("desktop.settings.writeSettings")(function* (inp ); }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/desktop/src/settings/DesktopSavedEnvironments.ts b/apps/desktop/src/settings/DesktopSavedEnvironments.ts index bdda7f9c7386..c763a9ed019b 100644 --- a/apps/desktop/src/settings/DesktopSavedEnvironments.ts +++ b/apps/desktop/src/settings/DesktopSavedEnvironments.ts @@ -9,7 +9,6 @@ import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as Path from "effect/Path"; import * as Schema from "effect/Schema"; -import * as Ref from "effect/Ref"; import * as DesktopEnvironment from "../app/DesktopEnvironment.ts"; import * as ElectronSafeStorage from "../electron/ElectronSafeStorage.ts"; @@ -365,6 +364,7 @@ function decodeSecretBytes( ); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; @@ -555,55 +555,3 @@ export const make = Effect.gen(function* () { }); export const layer = Layer.effect(DesktopSavedEnvironments, make); - -export const layerTest = (input?: { - readonly records?: readonly PersistedSavedEnvironmentRecord[]; - readonly secrets?: ReadonlyMap; -}) => - Layer.effect( - DesktopSavedEnvironments, - Effect.gen(function* () { - const recordsRef = yield* Ref.make(input?.records ?? []); - const secretsRef = yield* Ref.make(new Map(input?.secrets ?? [])); - - return DesktopSavedEnvironments.of({ - getRegistry: Ref.get(recordsRef), - setRegistry: (records) => Ref.set(recordsRef, records), - removeEnvironment: (environmentId) => - Ref.update(recordsRef, (records) => - records.filter((record) => record.environmentId !== environmentId), - ).pipe( - Effect.andThen( - Ref.update(secretsRef, (secrets) => { - const nextSecrets = new Map(secrets); - nextSecrets.delete(environmentId); - return nextSecrets; - }), - ), - ), - getSecret: (environmentId) => - Ref.get(secretsRef).pipe( - Effect.map((secrets) => Option.fromNullishOr(secrets.get(environmentId))), - ), - setSecret: ({ environmentId, secret }) => - Ref.get(recordsRef).pipe( - Effect.flatMap((records) => { - if (!records.some((record) => record.environmentId === environmentId)) { - return Effect.succeed(false); - } - return Ref.update(secretsRef, (secrets) => { - const nextSecrets = new Map(secrets); - nextSecrets.set(environmentId, secret); - return nextSecrets; - }).pipe(Effect.as(true)); - }), - ), - removeSecret: (environmentId) => - Ref.update(secretsRef, (secrets) => { - const nextSecrets = new Map(secrets); - nextSecrets.delete(environmentId); - return nextSecrets; - }), - }); - }), - ); diff --git a/apps/desktop/src/shell/DesktopShellEnvironment.ts b/apps/desktop/src/shell/DesktopShellEnvironment.ts index b4610eee5c84..57710a5075f7 100644 --- a/apps/desktop/src/shell/DesktopShellEnvironment.ts +++ b/apps/desktop/src/shell/DesktopShellEnvironment.ts @@ -533,6 +533,7 @@ const installShellEnvironment = ( return Effect.void; }; +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/desktop/src/ssh/DesktopSshEnvironment.ts b/apps/desktop/src/ssh/DesktopSshEnvironment.ts index 2c9ab0c03e48..659fdc648127 100644 --- a/apps/desktop/src/ssh/DesktopSshEnvironment.ts +++ b/apps/desktop/src/ssh/DesktopSshEnvironment.ts @@ -128,6 +128,7 @@ const makePasswordPrompt = ( prompts.request(request).pipe(Effect.mapError(toSshPasswordPromptError)), }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const manager = yield* SshTunnel.SshEnvironmentManager; const prompts = yield* DesktopSshPasswordPrompts.DesktopSshPasswordPrompts; diff --git a/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts b/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts index aa25d8135c7a..ec761605c328 100644 --- a/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts +++ b/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts @@ -222,6 +222,7 @@ const failPending = ( error: DesktopSshPasswordPromptRequestError, ) => Deferred.fail(pending.deferred, error).pipe(Effect.asVoid); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("desktop.sshPasswordPrompts.make")(function* ( options: DesktopSshPasswordPromptsOptions = {}, ) { diff --git a/apps/desktop/src/telemetry/DesktopTelemetryPublisher.ts b/apps/desktop/src/telemetry/DesktopTelemetryPublisher.ts index 3f56ace15fb1..c6ca7b1c9413 100644 --- a/apps/desktop/src/telemetry/DesktopTelemetryPublisher.ts +++ b/apps/desktop/src/telemetry/DesktopTelemetryPublisher.ts @@ -145,6 +145,7 @@ function sampleInterval( return LIVE_SAMPLE_INTERVAL; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("desktop.telemetryPublisher.make")(function* () { const electronApp = yield* ElectronApp.ElectronApp; const powerMonitor = yield* ElectronPowerMonitor.ElectronPowerMonitor; diff --git a/apps/desktop/src/updates/DesktopUpdates.ts b/apps/desktop/src/updates/DesktopUpdates.ts index 344d135a1024..3ea1574c4d8d 100644 --- a/apps/desktop/src/updates/DesktopUpdates.ts +++ b/apps/desktop/src/updates/DesktopUpdates.ts @@ -271,6 +271,7 @@ function isArm64HostRunningIntelBuild(runtimeInfo: DesktopRuntimeInfo): boolean return runtimeInfo.hostArch === "arm64" && runtimeInfo.appArch === "x64"; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const config = yield* DesktopConfig.DesktopConfig; const pool = yield* DesktopBackendPool.DesktopBackendPool; diff --git a/apps/desktop/src/updates/remoteUpdateFlow.ts b/apps/desktop/src/updates/remoteUpdateFlow.ts index 50b077313330..20043ba22cca 100644 --- a/apps/desktop/src/updates/remoteUpdateFlow.ts +++ b/apps/desktop/src/updates/remoteUpdateFlow.ts @@ -31,7 +31,7 @@ export const MAX_REMOTE_UPDATE_CHECKS = 2; export const MAX_REMOTE_UPDATE_DOWNLOADS = 3; /** Same predicate DesktopUpdates.installDownloadedUpdate uses for admission. */ -export function isInstallableDesktopUpdateState(state: DesktopUpdateState): boolean { +function isInstallableDesktopUpdateState(state: DesktopUpdateState): boolean { return ( state.downloadedVersion !== null && (state.status === "downloaded" || diff --git a/apps/desktop/src/updates/updateMachine.ts b/apps/desktop/src/updates/updateMachine.ts index 2e9ed5199a3e..85d8782ea668 100644 --- a/apps/desktop/src/updates/updateMachine.ts +++ b/apps/desktop/src/updates/updateMachine.ts @@ -5,13 +5,13 @@ import type { DesktopUpdateState, } from "@t3tools/contracts"; -export function nextStatusAfterDownloadFailure( +function nextStatusAfterDownloadFailure( currentState: DesktopUpdateState, ): DesktopUpdateState["status"] { return currentState.availableVersion ? "available" : "error"; } -export function getCanRetryAfterDownloadFailure(currentState: DesktopUpdateState): boolean { +function getCanRetryAfterDownloadFailure(currentState: DesktopUpdateState): boolean { return currentState.availableVersion !== null; } diff --git a/apps/desktop/src/window/DesktopApplicationMenu.ts b/apps/desktop/src/window/DesktopApplicationMenu.ts index 66244534debf..1ed68142033f 100644 --- a/apps/desktop/src/window/DesktopApplicationMenu.ts +++ b/apps/desktop/src/window/DesktopApplicationMenu.ts @@ -103,6 +103,7 @@ const handleCheckForUpdatesMenuClick = Effect.gen(function* () { yield* checkForUpdatesFromMenu; }).pipe(Effect.withSpan("desktop.menu.handleCheckForUpdatesClick")); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const electronApp = yield* ElectronApp.ElectronApp; const electronMenu = yield* ElectronMenu.ElectronMenu; diff --git a/apps/desktop/src/window/DesktopWindow.ts b/apps/desktop/src/window/DesktopWindow.ts index d87c74428a99..133285ab4167 100644 --- a/apps/desktop/src/window/DesktopWindow.ts +++ b/apps/desktop/src/window/DesktopWindow.ts @@ -278,6 +278,7 @@ function bindFirstRevealTrigger( } } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const assets = yield* DesktopAssets.DesktopAssets; diff --git a/apps/desktop/src/wsl/DesktopWslServerTree.ts b/apps/desktop/src/wsl/DesktopWslServerTree.ts index c6094e780caf..09d5331c9ade 100644 --- a/apps/desktop/src/wsl/DesktopWslServerTree.ts +++ b/apps/desktop/src/wsl/DesktopWslServerTree.ts @@ -116,6 +116,7 @@ const copyTree = ( }), ); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fs = yield* FileSystem.FileSystem; diff --git a/apps/mobile/package.json b/apps/mobile/package.json index b6f445d7eab0..b2e665917131 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -101,6 +101,7 @@ "expo-splash-screen": "~57.0.8", "expo-sqlite": "~57.0.2", "expo-symbols": "~57.0.2", + "expo-system-ui": "~57.0.3", "expo-updates": "~57.0.19", "expo-video": "~57.0.3", "expo-web-browser": "~57.0.2", diff --git a/apps/mobile/plugins/lib/addWidgetAssetCatalog.cjs b/apps/mobile/plugins/lib/addWidgetAssetCatalog.cjs index 817b7b9f6af5..de29d21531ee 100644 --- a/apps/mobile/plugins/lib/addWidgetAssetCatalog.cjs +++ b/apps/mobile/plugins/lib/addWidgetAssetCatalog.cjs @@ -47,7 +47,7 @@ function findByName(map, name) { } /** - * @param {import('xcode').XcodeProject} proj + * @param {import('expo/config-plugins').XcodeProject} proj * @param {{ targetName: string }} opts */ function addWidgetAssetCatalog(proj, opts) { diff --git a/apps/mobile/src/components/CompactBrandTitle.tsx b/apps/mobile/src/components/CompactBrandTitle.tsx index a6e2a7fd2121..ebac5656af0d 100644 --- a/apps/mobile/src/components/CompactBrandTitle.tsx +++ b/apps/mobile/src/components/CompactBrandTitle.tsx @@ -55,7 +55,7 @@ export function CompactBrandTitle( ); } -export function renderCompactBrandTitle() { +function renderCompactBrandTitle() { return ; } diff --git a/apps/mobile/src/components/EnvironmentMachineSymbol.tsx b/apps/mobile/src/components/EnvironmentMachineSymbol.tsx index 968040fd4113..e3fa01738991 100644 --- a/apps/mobile/src/components/EnvironmentMachineSymbol.tsx +++ b/apps/mobile/src/components/EnvironmentMachineSymbol.tsx @@ -13,7 +13,7 @@ const SYMBOL_BY_KIND: Record = { "mac-studio": "macstudio", }; -export const ENVIRONMENT_MACHINE_KIND_LABELS: Record = { +const ENVIRONMENT_MACHINE_KIND_LABELS: Record = { server: "Server", cloud: "Cloud VM", linux: "Linux/WSL", diff --git a/apps/mobile/src/components/StatusPill.tsx b/apps/mobile/src/components/StatusPill.tsx index 03985463aa85..2d7261002db8 100644 --- a/apps/mobile/src/components/StatusPill.tsx +++ b/apps/mobile/src/components/StatusPill.tsx @@ -1,37 +1,5 @@ -import { View } from "react-native"; - -import { AppText as Text } from "./AppText"; -import { cn } from "../lib/cn"; - export interface StatusTone { readonly label: string; readonly pillClassName: string; readonly textClassName: string; } - -export function StatusPill( - props: StatusTone & { - readonly size?: "default" | "compact"; - }, -) { - const size = props.size ?? "default"; - return ( - - - {props.label} - - - ); -} diff --git a/apps/mobile/src/features/cloud/cloudDebugLog.ts b/apps/mobile/src/features/cloud/cloudDebugLog.ts index 840a3db55680..b3ee4d0857d4 100644 --- a/apps/mobile/src/features/cloud/cloudDebugLog.ts +++ b/apps/mobile/src/features/cloud/cloudDebugLog.ts @@ -1,4 +1,4 @@ -export function isCloudDebugEnabled(): boolean { +function isCloudDebugEnabled(): boolean { return ( (typeof __DEV__ !== "undefined" && __DEV__) || (typeof globalThis !== "undefined" && diff --git a/apps/mobile/src/features/cloud/linkEnvironment.ts b/apps/mobile/src/features/cloud/linkEnvironment.ts index b8dc8f878e0c..f740d1cd9d51 100644 --- a/apps/mobile/src/features/cloud/linkEnvironment.ts +++ b/apps/mobile/src/features/cloud/linkEnvironment.ts @@ -367,7 +367,7 @@ export function listCloudEnvironments(input: { }); } -export function getCloudEnvironmentStatus(input: { +function getCloudEnvironmentStatus(input: { readonly clerkToken: string; readonly environment: RelayClientEnvironmentRecord; readonly relayScopes?: ReadonlyArray; @@ -397,7 +397,7 @@ export function getCloudEnvironmentStatus(input: { }); } -export function loadCloudEnvironmentStatuses(input: { +function loadCloudEnvironmentStatuses(input: { readonly clerkToken: string; readonly environments: ReadonlyArray; }): Effect.Effect< diff --git a/apps/mobile/src/features/cloud/managedRelayState.ts b/apps/mobile/src/features/cloud/managedRelayState.ts index 8c41d74841e7..774b8e4328b8 100644 --- a/apps/mobile/src/features/cloud/managedRelayState.ts +++ b/apps/mobile/src/features/cloud/managedRelayState.ts @@ -1,12 +1,8 @@ -import { useAtomValue } from "@effect/atom-react"; import { createManagedRelayQueryManager, managedRelaySessionAtom, - readManagedRelaySnapshotState, } from "@t3tools/client-runtime/relay"; -import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay"; -import { AsyncResult, Atom } from "effect/unstable/reactivity"; -import { useCallback, useEffect } from "react"; +import { Atom } from "effect/unstable/reactivity"; import { runtimeContextLayer } from "../../lib/runtime"; import { appAtomRegistry } from "../../state/atom-registry"; @@ -14,44 +10,11 @@ import { cloudDebugLog } from "./cloudDebugLog"; const managedRelayAtomRuntime = Atom.runtime(runtimeContextLayer); -export const managedRelayQueryManager = createManagedRelayQueryManager(managedRelayAtomRuntime, { +const managedRelayQueryManager = createManagedRelayQueryManager(managedRelayAtomRuntime, { onQueryEvent: (event) => cloudDebugLog(`query:${event.operation}:${event.stage}:${event.phase}`, { ...event }), }); -const EMPTY_ENVIRONMENTS_ATOM = Atom.make( - AsyncResult.success>([]), -).pipe(Atom.keepAlive, Atom.withLabel("managed-relay:mobile:environments:null")); - -export function useManagedRelayEnvironments() { - const session = useAtomValue(managedRelaySessionAtom); - const accountId = session?.accountId ?? null; - const atom = accountId - ? managedRelayQueryManager.environmentsAtom(accountId) - : EMPTY_ENVIRONMENTS_ATOM; - const result = useAtomValue(atom); - const snapshot = readManagedRelaySnapshotState(result); - useEffect(() => { - if (snapshot.error) { - console.error("[t3-cloud] Relay environment listing failed", { - message: snapshot.error, - traceId: snapshot.errorTraceId, - }); - } - }, [snapshot.error, snapshot.errorTraceId]); - const refresh = useCallback(() => { - if (accountId) { - managedRelayQueryManager.refreshEnvironments(appAtomRegistry, accountId); - } - }, [accountId]); - - return { - ...snapshot, - accountId, - refresh, - }; -} - export function refreshManagedRelayEnvironments(): void { const session = appAtomRegistry.get(managedRelaySessionAtom); if (session) { diff --git a/apps/mobile/src/features/connection/ConnectionSheetButton.tsx b/apps/mobile/src/features/connection/ConnectionSheetButton.tsx index fe26c66a355e..2bc294b14e6e 100644 --- a/apps/mobile/src/features/connection/ConnectionSheetButton.tsx +++ b/apps/mobile/src/features/connection/ConnectionSheetButton.tsx @@ -4,28 +4,6 @@ import { Platform, Pressable } from "react-native"; import { AppText as Text } from "../../components/AppText"; import { cn } from "../../lib/cn"; -const CARD_SHADOW = Platform.select({ - ios: { - shadowColor: "rgba(23,23,23,0.08)", - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 1, - shadowRadius: 16, - }, - android: { elevation: 3 }, -}); - -const CARD_SHADOW_DARK = Platform.select({ - ios: { - shadowColor: "#000", - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.18, - shadowRadius: 8, - }, - android: { elevation: 4 }, -}); - -export { CARD_SHADOW, CARD_SHADOW_DARK }; - export function ConnectionSheetButton(props: { readonly icon: React.ComponentProps["name"]; readonly label: string; diff --git a/apps/mobile/src/features/diffs/nativeReviewDiffHighlighter.ts b/apps/mobile/src/features/diffs/nativeReviewDiffHighlighter.ts index e924ff1aa645..93cb41a6888b 100644 --- a/apps/mobile/src/features/diffs/nativeReviewDiffHighlighter.ts +++ b/apps/mobile/src/features/diffs/nativeReviewDiffHighlighter.ts @@ -25,7 +25,7 @@ export class NativeReviewDiffHighlighterUnavailableError extends Schema.TaggedEr } } -export const isNativeReviewDiffHighlighterUnavailableError = Schema.is( +const isNativeReviewDiffHighlighterUnavailableError = Schema.is( NativeReviewDiffHighlighterUnavailableError, ); @@ -294,7 +294,7 @@ async function createJavascriptReviewDiffHighlighter(): Promise { if (engine === "javascript") { diff --git a/apps/mobile/src/features/files/filePath.ts b/apps/mobile/src/features/files/filePath.ts index 2598b58d7c9b..4503594b1e58 100644 --- a/apps/mobile/src/features/files/filePath.ts +++ b/apps/mobile/src/features/files/filePath.ts @@ -1,11 +1,5 @@ import { isWorkspaceVideoPreviewPath } from "@t3tools/shared/filePreview"; -export interface FileBreadcrumb { - readonly label: string; - readonly path: string; - readonly kind: "project" | "directory" | "file"; -} - function isWindowsAbsolutePath(value: string): boolean { return /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\"); } @@ -107,15 +101,3 @@ export function isSvgImagePreviewFile(path: string): boolean { export function isMarkdownPreviewFile(path: string): boolean { return /\.(?:md|mdx)$/i.test(path.split(/[?#]/, 1)[0] ?? ""); } - -export function fileBreadcrumbs(projectName: string, relativePath: string): FileBreadcrumb[] { - const parts = relativePath.split("/").filter(Boolean); - return [ - { label: projectName, path: "", kind: "project" }, - ...parts.map((part, index) => ({ - label: part, - path: parts.slice(0, index + 1).join("/"), - kind: index === parts.length - 1 ? ("file" as const) : ("directory" as const), - })), - ]; -} diff --git a/apps/mobile/src/features/home/thread-swipe-actions.tsx b/apps/mobile/src/features/home/thread-swipe-actions.tsx index 44f3c36e6655..988bb047b051 100644 --- a/apps/mobile/src/features/home/thread-swipe-actions.tsx +++ b/apps/mobile/src/features/home/thread-swipe-actions.tsx @@ -49,8 +49,8 @@ const ACTION_ICON_SIZE = 15; const COMPACT_ACTION_CIRCLE_SIZE = 28; const COMPACT_ACTION_ICON_SIZE = 13; -export const THREAD_SWIPE_ACTIONS_WIDTH = ACTION_ITEM_WIDTH * 2; -export const THREAD_SWIPE_SPRING = { +const THREAD_SWIPE_ACTIONS_WIDTH = ACTION_ITEM_WIDTH * 2; +const THREAD_SWIPE_SPRING = { damping: 26, mass: 0.7, overshootClamping: true, @@ -677,7 +677,7 @@ function SwipeActionButton(props: { ); } -export function ThreadSwipeActions(props: { +function ThreadSwipeActions(props: { readonly backgroundColor: ColorValue; readonly compact: boolean; readonly fullSwipeAction?: "delete" | "primary"; diff --git a/apps/mobile/src/features/observability/tracing.ts b/apps/mobile/src/features/observability/tracing.ts index eb73abba292b..314ed2249106 100644 --- a/apps/mobile/src/features/observability/tracing.ts +++ b/apps/mobile/src/features/observability/tracing.ts @@ -14,7 +14,7 @@ export interface TracingResource { readonly appVariant: string; } -export function resolveTracingConfig(): TracingConfig | null { +function resolveTracingConfig(): TracingConfig | null { const config = resolveCloudPublicConfig(); if (!hasTracingPublicConfig(config)) { return null; diff --git a/apps/mobile/src/features/review/reviewCommentSelection.ts b/apps/mobile/src/features/review/reviewCommentSelection.ts index 8ec9bbb43a3a..c9ea5dc6e34b 100644 --- a/apps/mobile/src/features/review/reviewCommentSelection.ts +++ b/apps/mobile/src/features/review/reviewCommentSelection.ts @@ -45,14 +45,14 @@ function emitChange() { listeners.forEach((listener) => listener()); } -export function subscribeReviewCommentTarget(listener: () => void): () => void { +function subscribeReviewCommentTarget(listener: () => void): () => void { listeners.add(listener); return () => { listeners.delete(listener); }; } -export function getReviewCommentTarget(): ReviewCommentTarget | null { +function getReviewCommentTarget(): ReviewCommentTarget | null { return currentTarget; } @@ -84,7 +84,7 @@ export function getReviewUnifiedLineNumber(line: ReviewRenderableLineRow): numbe return line.newLineNumber ?? line.oldLineNumber; } -export function getReviewChangeMarker(change: ReviewRenderableLineRow["change"]): string { +function getReviewChangeMarker(change: ReviewRenderableLineRow["change"]): string { if (change === "add") return "+"; if (change === "delete") return "-"; return " "; diff --git a/apps/mobile/src/features/review/reviewDiffRendering.tsx b/apps/mobile/src/features/review/reviewDiffRendering.tsx index d00cf2be4daf..4d115d5733b0 100644 --- a/apps/mobile/src/features/review/reviewDiffRendering.tsx +++ b/apps/mobile/src/features/review/reviewDiffRendering.tsx @@ -12,7 +12,7 @@ export const REVIEW_MONO_FONT_FAMILY = Platform.select({ default: "monospace", }); -export const REVIEW_DIFF_LINE_HEIGHT = MOBILE_CODE_SURFACE.rowHeight; +const REVIEW_DIFF_LINE_HEIGHT = MOBILE_CODE_SURFACE.rowHeight; export function renderVisibleWhitespace(value: string): string { const expandedTabs = value.replace(/\t/g, " "); @@ -25,7 +25,7 @@ export function changeTone(change: ReviewRenderableLineRow["change"]): string { return "bg-card"; } -export function changeBarTone(change: ReviewRenderableLineRow["change"]): string { +function changeBarTone(change: ReviewRenderableLineRow["change"]): string { if (change === "add") return "bg-emerald-400"; if (change === "delete") return "bg-rose-400"; return "bg-border/50"; diff --git a/apps/mobile/src/features/review/reviewPerf.ts b/apps/mobile/src/features/review/reviewPerf.ts index 2ae1095b1c6a..549437c6cdb6 100644 --- a/apps/mobile/src/features/review/reviewPerf.ts +++ b/apps/mobile/src/features/review/reviewPerf.ts @@ -14,7 +14,7 @@ function getPerformance(): ReviewPerformanceLike | null { return candidate ?? null; } -export function isReviewPerfEnabled(): boolean { +function isReviewPerfEnabled(): boolean { return typeof __DEV__ !== "undefined" ? __DEV__ : false; } @@ -42,33 +42,6 @@ export function measureReviewWork(name: string, callback: () => T): T { } } -export async function measureReviewAsyncWork( - name: string, - callback: () => Promise, -): Promise { - if (!isReviewPerfEnabled()) { - return callback(); - } - - const perf = getPerformance(); - const marker = `${REVIEW_PERF_PREFIX}.${name}.${reviewPerfSequence++}`; - const startMark = `${marker}.start`; - const endMark = `${marker}.end`; - const startedAt = perf?.now?.() ?? Date.now(); - - perf?.mark?.(startMark); - try { - return await callback(); - } finally { - const durationMs = (perf?.now?.() ?? Date.now()) - startedAt; - perf?.mark?.(endMark); - perf?.measure?.(`${REVIEW_PERF_PREFIX}.${name}`, startMark, endMark); - perf?.clearMarks?.(startMark); - perf?.clearMarks?.(endMark); - console.log(`[review-perf] ${name}`, { durationMs: Number(durationMs.toFixed(2)) }); - } -} - export function markReviewEvent(name: string, details?: Record): void { if (!isReviewPerfEnabled()) { return; diff --git a/apps/mobile/src/features/review/shikiReviewHighlighter.ts b/apps/mobile/src/features/review/shikiReviewHighlighter.ts index 8fa7f69a433c..416701be0b25 100644 --- a/apps/mobile/src/features/review/shikiReviewHighlighter.ts +++ b/apps/mobile/src/features/review/shikiReviewHighlighter.ts @@ -180,7 +180,6 @@ const languageAliases: Record = { txt: "text", }; let highlighterPromise: Promise | null = null; -let activeHighlighterEnginePromise: Promise | null = null; type LoadedLanguageModule = { default: Parameters[0]; @@ -317,13 +316,6 @@ async function getHighlighter(): Promise { .then((result) => result.highlighter) .catch((error) => { highlighterPromise = null; - activeHighlighterEnginePromise = null; - throw error; - }); - activeHighlighterEnginePromise = configuredHighlighterPromise - .then((result) => result.engine) - .catch((error) => { - activeHighlighterEnginePromise = null; throw error; }); } @@ -331,31 +323,6 @@ async function getHighlighter(): Promise { return highlighterPromise; } -export async function getActiveReviewHighlighterEngine(): Promise { - await getHighlighter(); - return activeHighlighterEnginePromise ?? Promise.resolve("javascript"); -} - -export async function prepareReviewHighlighter(): Promise { - await getHighlighter(); -} - -export async function prepareReviewHighlighterLanguages( - languages: ReadonlyArray, -): Promise { - const highlighter = await getHighlighter(); - await Promise.all( - languages.map(async (language) => { - const candidate = resolveLanguageAlias(language); - if (candidate === "text" || !(candidate in languageImports)) { - return; - } - - await loadSingleLanguage(highlighter, candidate); - }), - ); -} - function resolveLanguageAlias(language: string): string { const normalized = language.toLowerCase(); return languageAliases[normalized] ?? normalized; diff --git a/apps/mobile/src/features/review/useNativeReviewDiffBridge.ts b/apps/mobile/src/features/review/useNativeReviewDiffBridge.ts index 1728da662686..af5f2bcca6b2 100644 --- a/apps/mobile/src/features/review/useNativeReviewDiffBridge.ts +++ b/apps/mobile/src/features/review/useNativeReviewDiffBridge.ts @@ -8,8 +8,6 @@ import { useNativeReviewDiffHighlighting } from "./useNativeReviewDiffHighlighti import { buildNativeReviewTokensResetKey } from "./reviewDiffBridgeKeys"; import { useUniwindTheme } from "../../lib/useUniwindTheme"; -export { buildNativeReviewTokensResetKey } from "./reviewDiffBridgeKeys"; - export function useNativeReviewDiffBridge(input: { readonly threadKey: string | null; readonly sectionId: string | null; diff --git a/apps/mobile/src/features/review/useReviewDiffData.ts b/apps/mobile/src/features/review/useReviewDiffData.ts index 85aa6b032fae..0cf76e30b4fa 100644 --- a/apps/mobile/src/features/review/useReviewDiffData.ts +++ b/apps/mobile/src/features/review/useReviewDiffData.ts @@ -25,7 +25,7 @@ function logReviewDiffDiagnostic(message: string, details?: Record void; } -export function sortAndDedupeIncomingShares( +function sortAndDedupeIncomingShares( drafts: ReadonlyArray, ): ReadonlyArray { const ids = new Set(); diff --git a/apps/mobile/src/features/showcase/nativeShowcaseScene.ts b/apps/mobile/src/features/showcase/nativeShowcaseScene.ts index 11618291932d..bfdf57df42e5 100644 --- a/apps/mobile/src/features/showcase/nativeShowcaseScene.ts +++ b/apps/mobile/src/features/showcase/nativeShowcaseScene.ts @@ -2,7 +2,7 @@ import { requireOptionalNativeModule } from "expo"; import { MOBILE_THEME_IDS, type MobileThemeId } from "../../lib/mobileTheme"; -export const SHOWCASE_SCENES = ["threads", "thread", "terminal", "review", "environments"] as const; +const SHOWCASE_SCENES = ["threads", "thread", "terminal", "review", "environments"] as const; export type ShowcaseScene = (typeof SHOWCASE_SCENES)[number]; export type ShowcaseOrientation = "portrait" | "landscape"; diff --git a/apps/mobile/src/features/terminal/nativeTerminalModule.ts b/apps/mobile/src/features/terminal/nativeTerminalModule.ts index f6a74595c80e..bdce002293fa 100644 --- a/apps/mobile/src/features/terminal/nativeTerminalModule.ts +++ b/apps/mobile/src/features/terminal/nativeTerminalModule.ts @@ -94,7 +94,3 @@ export function getNativeTerminalHardwareKeyRevision(): number | null { return null; } } - -export function hasNativeTerminalSurface() { - return resolveNativeTerminalSurfaceView() !== null; -} diff --git a/apps/mobile/src/features/terminal/terminalDebugLog.ts b/apps/mobile/src/features/terminal/terminalDebugLog.ts index eb11419b330c..1f19e6414d9f 100644 --- a/apps/mobile/src/features/terminal/terminalDebugLog.ts +++ b/apps/mobile/src/features/terminal/terminalDebugLog.ts @@ -4,7 +4,7 @@ * Enabled when `__DEV__` is true, or set `globalThis.__T3_TERMINAL_DEBUG__ = true` in a JS * debugger / Metro console to trace release/TestFlight builds. */ -export function isTerminalDebugEnabled(): boolean { +function isTerminalDebugEnabled(): boolean { return ( (typeof __DEV__ !== "undefined" && __DEV__) || (typeof globalThis !== "undefined" && diff --git a/apps/mobile/src/features/terminal/terminalMenu.ts b/apps/mobile/src/features/terminal/terminalMenu.ts index 06cb74e9467d..739e4a35cb23 100644 --- a/apps/mobile/src/features/terminal/terminalMenu.ts +++ b/apps/mobile/src/features/terminal/terminalMenu.ts @@ -4,11 +4,7 @@ import { nextTerminalId, resolveTerminalSessionLabel } from "@t3tools/shared/ter import * as Arr from "effect/Array"; import * as Order from "effect/Order"; -export { - getTerminalLabel, - nextTerminalId, - resolveTerminalSessionLabel, -} from "@t3tools/shared/terminalLabels"; +export { resolveTerminalSessionLabel } from "@t3tools/shared/terminalLabels"; export interface TerminalMenuSession { readonly terminalId: string; diff --git a/apps/mobile/src/features/threads/markdownCodeHighlightState.ts b/apps/mobile/src/features/threads/markdownCodeHighlightState.ts index c415cf739809..ab3b16ea08ac 100644 --- a/apps/mobile/src/features/threads/markdownCodeHighlightState.ts +++ b/apps/mobile/src/features/threads/markdownCodeHighlightState.ts @@ -31,7 +31,7 @@ class MarkdownCodeHighlightError extends Data.TaggedError("MarkdownCodeHighlight readonly cause: unknown; }> {} -export function createMarkdownCodeHighlightAtomFamily(options?: { +function createMarkdownCodeHighlightAtomFamily(options?: { readonly highlight?: MarkdownCodeHighlighter; readonly idleTtlMs?: number; }) { @@ -61,7 +61,7 @@ export function createMarkdownCodeHighlightAtomFamily(options?: { return (input: MarkdownCodeHighlightInput) => family(new MarkdownCodeHighlightCacheKey(input)); } -export const markdownCodeHighlightAtom = createMarkdownCodeHighlightAtomFamily(); +const markdownCodeHighlightAtom = createMarkdownCodeHighlightAtomFamily(); export function useMarkdownCodeHighlight(input: { readonly code: string; diff --git a/apps/mobile/src/features/threads/thread-list-items.tsx b/apps/mobile/src/features/threads/thread-list-items.tsx index 7a677a5ec797..758a9ef792f7 100644 --- a/apps/mobile/src/features/threads/thread-list-items.tsx +++ b/apps/mobile/src/features/threads/thread-list-items.tsx @@ -40,7 +40,7 @@ import { ThreadSearchMatchExcerpt } from "./thread-search-match"; export type ThreadListVariant = "compact" | "sidebar"; /** Left inset that aligns compact secondary rows with the title column. */ -export const THREAD_LIST_COMPACT_INSET = HOME_HORIZONTAL_INSET; +const THREAD_LIST_COMPACT_INSET = HOME_HORIZONTAL_INSET; const SIDEBAR_ROW_RADIUS = 12; function pullRequestTintColor( diff --git a/apps/mobile/src/features/threads/thread-list-v2-items.tsx b/apps/mobile/src/features/threads/thread-list-v2-items.tsx index 2d5251fb5f8d..cfa357229491 100644 --- a/apps/mobile/src/features/threads/thread-list-v2-items.tsx +++ b/apps/mobile/src/features/threads/thread-list-v2-items.tsx @@ -90,7 +90,7 @@ const LEGACY_MENU_ACTIONS: MenuAction[] = [ const SIDEBAR_V2_ROW_RADIUS = 12; /** Section label + rule: the only structure in an otherwise flat list. */ -export const ThreadListV2SectionDivider = memo(function ThreadListV2SectionDivider(props: { +const ThreadListV2SectionDivider = memo(function ThreadListV2SectionDivider(props: { readonly label: string; readonly pane?: "screen" | "sidebar"; }) { diff --git a/apps/mobile/src/features/threads/threadListV2.ts b/apps/mobile/src/features/threads/threadListV2.ts index 3629e63df462..a943eb99529a 100644 --- a/apps/mobile/src/features/threads/threadListV2.ts +++ b/apps/mobile/src/features/threads/threadListV2.ts @@ -23,8 +23,6 @@ import { type PendingThreadOrder, } from "./threadOrder"; -export { snoozeWakeLabel }; - /** * Thread List v2 model, ported from the web sidebar v2 * (apps/web/src/components/Sidebar.logic.ts + SidebarV2.tsx). diff --git a/apps/mobile/src/features/updates/app-updates.ts b/apps/mobile/src/features/updates/app-updates.ts index 5f8a110beaf6..443c00057de0 100644 --- a/apps/mobile/src/features/updates/app-updates.ts +++ b/apps/mobile/src/features/updates/app-updates.ts @@ -501,7 +501,7 @@ function defaultOnNextBackground(apply: () => void, includeCurrent: boolean): vo * install prompt appears. Long enough that most sessions background naturally * and install silently instead. */ -export const DEFERRED_INSTALL_PROMPT_AFTER_MS = 30 * 60 * 1000; +const DEFERRED_INSTALL_PROMPT_AFTER_MS = 30 * 60 * 1000; /** * The window resets on every backgrounding because that is exactly when the @@ -590,7 +590,7 @@ export function shouldRecheckAppUpdateOnForeground( ); } -export function createAppUpdateForegroundRecheck( +function createAppUpdateForegroundRecheck( client: AppUpdateClient = Updates, deferral: AppUpdateDeferral = appUpdateDeferral, ): () => void { diff --git a/apps/mobile/src/lib/appearancePreferences.ts b/apps/mobile/src/lib/appearancePreferences.ts index 2ce6a8b5a367..9ec0715c12a0 100644 --- a/apps/mobile/src/lib/appearancePreferences.ts +++ b/apps/mobile/src/lib/appearancePreferences.ts @@ -12,7 +12,7 @@ export const MIN_BASE_FONT_SIZE = 11; export const MAX_BASE_FONT_SIZE = 22; export const BASE_FONT_SIZE_STEP = 1; -export const DEFAULT_CODE_FONT_SIZE = MOBILE_CODE_SURFACE.fontSize; +const DEFAULT_CODE_FONT_SIZE = MOBILE_CODE_SURFACE.fontSize; export const MIN_CODE_FONT_SIZE = 8; export const MAX_CODE_FONT_SIZE = 18; export const CODE_FONT_SIZE_STEP = 1; @@ -241,10 +241,4 @@ export function stepTerminalFontSize(current: number, direction: -1 | 1): number return normalizeTerminalFontSize(next); } -export { - DEFAULT_TERMINAL_FONT_SIZE, - MAX_TERMINAL_FONT_SIZE, - MIN_TERMINAL_FONT_SIZE, - TERMINAL_FONT_SIZE_STEP, - normalizeTerminalFontSize, -}; +export { MAX_TERMINAL_FONT_SIZE, MIN_TERMINAL_FONT_SIZE, TERMINAL_FONT_SIZE_STEP }; diff --git a/apps/mobile/src/lib/layout.ts b/apps/mobile/src/lib/layout.ts index ee38ac020e74..ff776403448e 100644 --- a/apps/mobile/src/lib/layout.ts +++ b/apps/mobile/src/lib/layout.ts @@ -15,10 +15,10 @@ function clamp(value: number, min: number, max: number): number { export const SPLIT_LAYOUT_MIN_WIDTH = 720; export const SPLIT_LAYOUT_MIN_HEIGHT = 600; -export const SPLIT_SIDEBAR_MIN_WIDTH = 280; +const SPLIT_SIDEBAR_MIN_WIDTH = 280; const SPLIT_SIDEBAR_DEFAULT_MAX_WIDTH = 380; -export const AUXILIARY_PANE_MIN_CONTENT_WIDTH = 960; +const AUXILIARY_PANE_MIN_CONTENT_WIDTH = 960; export const CHAT_CONTENT_MAX_WIDTH = 960; // min-h-8 uses the 14px rem configured in metro.config.js. export const THREAD_WORK_ROW_MIN_HEIGHT = 28; @@ -44,8 +44,8 @@ export function deriveThreadWorkLogSizing(input: { }; } -export const AUXILIARY_PANE_MIN_WIDTH = 260; -export const AUXILIARY_PANE_MAX_WIDTH = 480; +const AUXILIARY_PANE_MIN_WIDTH = 260; +const AUXILIARY_PANE_MAX_WIDTH = 480; const AUXILIARY_PANE_DEFAULT_MAX_WIDTH = 320; const FILE_INSPECTOR_MIN_VIEWPORT_WIDTH = 820; const FILE_INSPECTOR_MIN_MAIN_WIDTH = 560; diff --git a/apps/mobile/src/lib/threadActivity.ts b/apps/mobile/src/lib/threadActivity.ts index f77f54cf625c..9d3f99265a22 100644 --- a/apps/mobile/src/lib/threadActivity.ts +++ b/apps/mobile/src/lib/threadActivity.ts @@ -1036,7 +1036,7 @@ function capitalizePhrase(value: string): string { * folded into the row, so "working" means a member has not reported a * terminal state yet. */ -export function agentSpawnLabel(spawn: NonNullable): string { +function agentSpawnLabel(spawn: NonNullable): string { const members = agentSpawnMembers(spawn); const count = Math.max(members.length, 1); const subjects = `${count} subagent${count === 1 ? "" : "s"}`; @@ -1804,7 +1804,7 @@ export function deriveThreadFeedPresentation( * list keeps one mounted row for the turn's live slot (mirrors web's * LIVE_ACTIVITY_ROW_ID). Anything keyed by row id must not distinguish them. */ -export const LIVE_ACTIVITY_ROW_ID = "live-activity-row"; +const LIVE_ACTIVITY_ROW_ID = "live-activity-row"; function thinkingRow(createdAt: string, turnId: TurnId | null) { if (cachedThinkingRow?.createdAt !== createdAt || cachedThinkingRow.turnId !== turnId) { diff --git a/apps/mobile/src/native/StackHeader.tsx b/apps/mobile/src/native/StackHeader.tsx index a524d5152473..5871ace4ca70 100644 --- a/apps/mobile/src/native/StackHeader.tsx +++ b/apps/mobile/src/native/StackHeader.tsx @@ -19,7 +19,6 @@ import type { ColorValue } from "react-native"; export { nativeHeaderScrollEdgeEffects, - nativeTopScrollEdgeEffect, type NativeHeaderScrollEdgeEffects, type NativeTopScrollEdgeEffect, } from "./scrollEdgeEffects"; diff --git a/apps/mobile/src/persistence/mobile-preferences.ts b/apps/mobile/src/persistence/mobile-preferences.ts index f14a73f15cb2..bfa4076518cb 100644 --- a/apps/mobile/src/persistence/mobile-preferences.ts +++ b/apps/mobile/src/persistence/mobile-preferences.ts @@ -179,6 +179,7 @@ function sanitizePreferences(parsed: Preferences): Preferences { return preferences; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("MobilePreferencesStore.make")(function* () { const database = yield* MobileDatabase.MobileDatabase; const secureStorage = yield* MobileSecureStorage.MobileSecureStorage; diff --git a/apps/mobile/src/persistence/mobile-secure-storage.ts b/apps/mobile/src/persistence/mobile-secure-storage.ts index 0ab7c9e4d960..d2b38fb3367f 100644 --- a/apps/mobile/src/persistence/mobile-secure-storage.ts +++ b/apps/mobile/src/persistence/mobile-secure-storage.ts @@ -28,6 +28,7 @@ export class MobileSecureStorage extends Context.Service< } >()("@t3tools/mobile/persistence/MobileSecureStorage") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = MobileSecureStorage.of({ getItem: Effect.fn("MobileSecureStorage.getItem")((key) => Effect.tryPromise({ diff --git a/apps/mobile/src/persistence/mobile-storage.ts b/apps/mobile/src/persistence/mobile-storage.ts index 266e8c1a9a8f..812af85f24a2 100644 --- a/apps/mobile/src/persistence/mobile-storage.ts +++ b/apps/mobile/src/persistence/mobile-storage.ts @@ -117,6 +117,7 @@ export class MobileStorage extends Context.Service< } >()("@t3tools/mobile/persistence/MobileStorage") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("MobileStorage.make")(function* () { const secureStorage = yield* MobileSecureStorage.MobileSecureStorage; diff --git a/apps/mobile/src/state/environments.ts b/apps/mobile/src/state/environments.ts index 88d80631ad31..29b2a48923b7 100644 --- a/apps/mobile/src/state/environments.ts +++ b/apps/mobile/src/state/environments.ts @@ -8,7 +8,6 @@ import { useMemo } from "react"; import { environmentCatalog } from "../connection/catalog"; import { environmentPresentations } from "./presentation"; -import { useEnvironmentQuery } from "./query"; export interface EnvironmentPresentation extends BaseEnvironmentPresentation { readonly environmentId: EnvironmentId; @@ -17,7 +16,7 @@ export interface EnvironmentPresentation extends BaseEnvironmentPresentation { readonly relayManaged: boolean; } -export function projectEnvironmentPresentation( +function projectEnvironmentPresentation( environmentId: EnvironmentId, presentation: BaseEnvironmentPresentation, ): EnvironmentPresentation { @@ -50,7 +49,3 @@ export function useEnvironments() { presentationById, }; } - -export function useEnvironmentConnectionState(environmentId: EnvironmentId) { - return useEnvironmentQuery(environmentCatalog.stateAtom(environmentId)); -} diff --git a/apps/mobile/src/state/preferences.ts b/apps/mobile/src/state/preferences.ts index d173cf55be5a..b602eb51aca5 100644 --- a/apps/mobile/src/state/preferences.ts +++ b/apps/mobile/src/state/preferences.ts @@ -118,7 +118,7 @@ export function createMobilePreferencesState(runtime: Atom.AtomRuntime>(n Atom.withLabel("mobile:thread-pr-snapshots"), ); -export { - presentThreadPr, - type ThreadPr, - type ThreadPrPresentation, -} from "./thread-pr-presentation"; +export { type ThreadPr, type ThreadPrPresentation } from "./thread-pr-presentation"; /** * Live status for a thread's server-provided PR. Visible rows share a summary diff --git a/apps/mobile/src/state/use-vcs-action-state.ts b/apps/mobile/src/state/use-vcs-action-state.ts index e169005a07fa..ffe7be3b2b9c 100644 --- a/apps/mobile/src/state/use-vcs-action-state.ts +++ b/apps/mobile/src/state/use-vcs-action-state.ts @@ -44,7 +44,7 @@ export function dismissGitActionResult(): void { broadcast(null); } -export function useGitActionResultNotification(): { +function useGitActionResultNotification(): { readonly result: GitActionResultNotification | null; readonly dismiss: () => void; } { diff --git a/apps/server/integration/NetworkTransferMeasurement.integration.ts b/apps/server/integration/NetworkTransferMeasurement.integration.ts index c18b7d14bfe4..d0a7d4995486 100644 --- a/apps/server/integration/NetworkTransferMeasurement.integration.ts +++ b/apps/server/integration/NetworkTransferMeasurement.integration.ts @@ -120,7 +120,7 @@ function rawDataBytes(data: NodeSocket.NodeWS.RawData): number { return data.byteLength; } -export function makeWebSocketTransferRecorder(): WebSocketTransferRecorder { +function makeWebSocketTransferRecorder(): WebSocketTransferRecorder { let socket: NodeWebSocketWithTransport | null = null; // Held separately from the WebSocket so wire totals survive a close, which // is when a reconnect measurement reads them. @@ -176,7 +176,7 @@ export function transferDelta( }; } -export function countingWsRpcProtocolLayer(input: { +function countingWsRpcProtocolLayer(input: { readonly url: string; readonly cookie: string; readonly recorder: WebSocketTransferRecorder; @@ -194,7 +194,7 @@ export function countingWsRpcProtocolLayer(input: { ); } -export const makeCountingWsRpcClient = RpcClient.make(WsRpcGroup); +const makeCountingWsRpcClient = RpcClient.make(WsRpcGroup); export type CountingWsRpcClient = Effect.Success; export interface MeasuredWsClient { diff --git a/apps/server/integration/OrchestrationEngineHarness.integration.ts b/apps/server/integration/OrchestrationEngineHarness.integration.ts index 1c035d5fa15a..53087d272503 100644 --- a/apps/server/integration/OrchestrationEngineHarness.integration.ts +++ b/apps/server/integration/OrchestrationEngineHarness.integration.ts @@ -28,11 +28,9 @@ import * as CheckpointStore from "../src/checkpointing/CheckpointStore.ts"; import { TextGeneration } from "../src/textGeneration/TextGeneration.ts"; import { OrchestrationCommandReceiptRepositoryLive } from "../src/persistence/Layers/OrchestrationCommandReceipts.ts"; import { OrchestrationEventStoreLive } from "../src/persistence/Layers/OrchestrationEventStore.ts"; -import { ProjectionCheckpointRepositoryLive } from "../src/persistence/Layers/ProjectionCheckpoints.ts"; import { ProjectionPendingApprovalRepositoryLive } from "../src/persistence/Layers/ProjectionPendingApprovals.ts"; import * as ProviderSessionRuntime from "../src/persistence/ProviderSessionRuntime.ts"; import { makeSqlitePersistenceLive } from "../src/persistence/Layers/Sqlite.ts"; -import { ProjectionCheckpointRepository } from "../src/persistence/Services/ProjectionCheckpoints.ts"; import { ProjectionPendingApprovalRepository } from "../src/persistence/Services/ProjectionPendingApprovals.ts"; import { makeAdapterRegistryMock } from "../src/provider/testUtils/providerAdapterRegistryMock.ts"; import { ProviderAdapterRegistry } from "../src/provider/Services/ProviderAdapterRegistry.ts"; @@ -190,7 +188,6 @@ export interface OrchestrationIntegrationHarness { readonly snapshotQuery: ProjectionSnapshotQuery["Service"]; readonly providerService: ProviderService["Service"]; readonly checkpointStore: CheckpointStore.CheckpointStore["Service"]; - readonly checkpointRepository: ProjectionCheckpointRepository["Service"]; readonly pendingApprovalRepository: ProjectionPendingApprovalRepository["Service"]; readonly waitForThread: ( threadId: string, @@ -314,7 +311,6 @@ export const makeOrchestrationIntegrationHarness = ( const runtimeServicesLayer = Layer.mergeAll( projectionSnapshotQueryLayer, orchestrationLayer.pipe(Layer.provide(projectionSnapshotQueryLayer)), - ProjectionCheckpointRepositoryLive, ProjectionPendingApprovalRepositoryLive, checkpointStoreLayer, providerLayer, @@ -451,10 +447,6 @@ export const makeOrchestrationIntegrationHarness = ( const checkpointStore = yield* tryRuntimePromise("load CheckpointStore service", () => runtime.runPromise(Effect.service(CheckpointStore.CheckpointStore)), ).pipe(Effect.orDie); - const checkpointRepository = yield* tryRuntimePromise( - "load ProjectionCheckpointRepository service", - () => runtime.runPromise(Effect.service(ProjectionCheckpointRepository)), - ).pipe(Effect.orDie); const pendingApprovalRepository = yield* tryRuntimePromise( "load ProjectionPendingApprovalRepository service", () => runtime.runPromise(Effect.service(ProjectionPendingApprovalRepository)), @@ -600,7 +592,6 @@ export const makeOrchestrationIntegrationHarness = ( snapshotQuery, providerService, checkpointStore, - checkpointRepository, pendingApprovalRepository, waitForThread, waitForDomainEvent, diff --git a/apps/server/integration/TransferBudgetReport.integration.ts b/apps/server/integration/TransferBudgetReport.integration.ts index d82688d2863f..fe0b3ed8e648 100644 --- a/apps/server/integration/TransferBudgetReport.integration.ts +++ b/apps/server/integration/TransferBudgetReport.integration.ts @@ -56,7 +56,7 @@ const TRANSFER_BUDGET = { measuredTurnWebSocketMessages: 21, } satisfies ProviderTransferBudget; -export const TRANSFER_BUDGETS: Readonly> = { +const TRANSFER_BUDGETS: Readonly> = { codex: TRANSFER_BUDGET, claudeAgent: TRANSFER_BUDGET, }; diff --git a/apps/server/integration/TransferBudgetScenario.integration.ts b/apps/server/integration/TransferBudgetScenario.integration.ts index 33e149dd2484..ccede4204f66 100644 --- a/apps/server/integration/TransferBudgetScenario.integration.ts +++ b/apps/server/integration/TransferBudgetScenario.integration.ts @@ -26,7 +26,7 @@ import { TRANSFER_HISTORY_TURN_COUNT, } from "./fixtures/transferBudget.ts"; -export const TRANSFER_PROJECT_ID = ProjectId.make("transfer-budget-project"); +const TRANSFER_PROJECT_ID = ProjectId.make("transfer-budget-project"); export const TRANSFER_THREAD_ID = ThreadId.make("transfer-budget-thread"); export const TRANSFER_MEASURED_TURN_INDEX = TRANSFER_HISTORY_TURN_COUNT; diff --git a/apps/server/integration/orchestrationEngine.integration.test.ts b/apps/server/integration/orchestrationEngine.integration.test.ts index ccfb9c467421..75b414ae4ce6 100644 --- a/apps/server/integration/orchestrationEngine.integration.test.ts +++ b/apps/server/integration/orchestrationEngine.integration.test.ts @@ -248,9 +248,9 @@ it.live("runs a single turn end-to-end and persists checkpoint state in sqlite + assert.equal(thread.checkpoints[0]?.status, "ready"); assert.equal(thread.checkpoints[0]?.checkpointTurnCount, 1); - const checkpointRows = yield* harness.checkpointRepository.listByThreadId({ - threadId: THREAD_ID, - }); + const { checkpoints: checkpointRows } = Option.getOrThrow( + yield* harness.snapshotQuery.getThreadCheckpointContext(THREAD_ID), + ); assert.equal(checkpointRows.length, 1); assert.equal(checkpointRows[0]?.checkpointTurnCount, 1); assert.equal(checkpointRows[0]?.status, "ready"); @@ -498,9 +498,9 @@ it.live("runs multi-turn file edits and persists checkpoint diffs", () => true, ); - const checkpointRows = yield* harness.checkpointRepository.listByThreadId({ - threadId: THREAD_ID, - }); + const { checkpoints: checkpointRows } = Option.getOrThrow( + yield* harness.snapshotQuery.getThreadCheckpointContext(THREAD_ID), + ); assert.deepEqual( checkpointRows.map((row) => row.checkpointTurnCount), [1, 2], @@ -688,14 +688,13 @@ it.live("records failed turn runtime state and checkpoint status as error", () = assert.equal(thread.session?.status, "error"); assert.equal(thread.checkpoints[0]?.status, "error"); - const checkpointRow = yield* harness.checkpointRepository.getByThreadAndTurnCount({ - threadId: THREAD_ID, - checkpointTurnCount: 1, - }); - assert.equal(Option.isSome(checkpointRow), true); - if (Option.isSome(checkpointRow)) { - assert.equal(checkpointRow.value.status, "error"); - } + const { checkpoints } = Option.getOrThrow( + yield* harness.snapshotQuery.getThreadCheckpointContext(THREAD_ID), + ); + assert.equal( + checkpoints.find((checkpoint) => checkpoint.checkpointTurnCount === 1)?.status, + "error", + ); assert.equal( gitRefExists(harness.workspaceDir, checkpointRefForThreadTurn(THREAD_ID, 1)), true, @@ -879,9 +878,9 @@ it.live("reverts to an earlier checkpoint and trims checkpoint projections + git ); assert.deepEqual(harness.adapterHarness!.getRollbackCalls(THREAD_ID), [1]); - const checkpointRows = yield* harness.checkpointRepository.listByThreadId({ - threadId: THREAD_ID, - }); + const { checkpoints: checkpointRows } = Option.getOrThrow( + yield* harness.snapshotQuery.getThreadCheckpointContext(THREAD_ID), + ); assert.equal(checkpointRows.length, 1); }), ), diff --git a/apps/server/scripts/t3-sqlite-state.ts b/apps/server/scripts/t3-sqlite-state.ts index 8423e7e6090f..78e84f6216f7 100644 --- a/apps/server/scripts/t3-sqlite-state.ts +++ b/apps/server/scripts/t3-sqlite-state.ts @@ -245,7 +245,7 @@ export const runSqliteState = Effect.fn("runSqliteState")(function* ( ); }); -export const t3SqliteStateCommand = Command.make( +const t3SqliteStateCommand = Command.make( "t3-sqlite-state", { operation: Argument.choice("operation", SqliteStateOperation.literals).pipe( diff --git a/apps/server/src/assets/NativeAppIconResolver.ts b/apps/server/src/assets/NativeAppIconResolver.ts index ba572650d408..956e5d4d6be2 100644 --- a/apps/server/src/assets/NativeAppIconResolver.ts +++ b/apps/server/src/assets/NativeAppIconResolver.ts @@ -206,6 +206,7 @@ const resolveNativeAppIconUncached = Effect.fn("NativeAppIconResolver.resolveUnc return yield* existingFile(cachePath); }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const hostPlatform = yield* HostProcessPlatform; diff --git a/apps/server/src/attachmentStore.ts b/apps/server/src/attachmentStore.ts index 261b094645b9..4f098e1e6298 100644 --- a/apps/server/src/attachmentStore.ts +++ b/apps/server/src/attachmentStore.ts @@ -22,7 +22,7 @@ const ATTACHMENT_ID_PATTERN = new RegExp( ); export const PENDING_ATTACHMENT_THREAD_SEGMENT = "pending"; -export const PENDING_ATTACHMENT_MAX_AGE_MS = 24 * 60 * 60 * 1000; +const PENDING_ATTACHMENT_MAX_AGE_MS = 24 * 60 * 60 * 1000; const PARTIAL_UPLOAD_MAX_AGE_MS = 60 * 60 * 1000; export function toSafeThreadAttachmentSegment(threadId: string): string | null { diff --git a/apps/server/src/auth/EnvironmentAuth.ts b/apps/server/src/auth/EnvironmentAuth.ts index b0406b6e6ecd..21330e2819e9 100644 --- a/apps/server/src/auth/EnvironmentAuth.ts +++ b/apps/server/src/auth/EnvironmentAuth.ts @@ -38,7 +38,7 @@ import * as SessionStore from "./SessionStore.ts"; import { verifyRequestDpopProof } from "./dpop.ts"; import { layerConfig as SqlitePersistenceLayer } from "../persistence/Layers/Sqlite.ts"; -export const DEFAULT_SESSION_SUBJECT = "cli-issued-session"; +const DEFAULT_SESSION_SUBJECT = "cli-issued-session"; export const INTERNAL_ADMINISTRATIVE_BOOTSTRAP_SUBJECT = "administrative-bootstrap"; export interface IssuedPairingLink { @@ -591,6 +591,7 @@ export function selectRequestCredential( return undefined; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const policy = yield* EnvironmentAuthPolicy.EnvironmentAuthPolicy; const bootstrapCredentials = yield* PairingGrantStore.PairingGrantStore; @@ -1033,7 +1034,7 @@ export const layer = Layer.effect(EnvironmentAuth, make).pipe( Layer.provideMerge(EnvironmentAuthPolicy.layer), ); -export const storageLayer = Layer.mergeAll(ServerSecretStore.layer, SqlitePersistenceLayer); +const storageLayer = Layer.mergeAll(ServerSecretStore.layer, SqlitePersistenceLayer); export const runtimeLayer = layer.pipe( Layer.provideMerge(storageLayer), diff --git a/apps/server/src/auth/EnvironmentAuthPolicy.ts b/apps/server/src/auth/EnvironmentAuthPolicy.ts index 446b8a8bba95..e2a4a539dc9d 100644 --- a/apps/server/src/auth/EnvironmentAuthPolicy.ts +++ b/apps/server/src/auth/EnvironmentAuthPolicy.ts @@ -14,6 +14,7 @@ export class EnvironmentAuthPolicy extends Context.Service< } >()("t3/auth/EnvironmentAuthPolicy") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const config = yield* ServerConfig.ServerConfig; const serverEnvironment = yield* ServerEnvironment.ServerEnvironmentIdentity; diff --git a/apps/server/src/auth/PairingGrantStore.ts b/apps/server/src/auth/PairingGrantStore.ts index d455d3ac451c..846f0e99e6b4 100644 --- a/apps/server/src/auth/PairingGrantStore.ts +++ b/apps/server/src/auth/PairingGrantStore.ts @@ -72,7 +72,6 @@ export const BootstrapCredentialInvalidError = Schema.Union([ UnavailableBootstrapCredentialError, ]); export type BootstrapCredentialInvalidError = typeof BootstrapCredentialInvalidError.Type; -export const isBootstrapCredentialInvalidError = Schema.is(BootstrapCredentialInvalidError); export class ActivePairingLinksLoadError extends Schema.TaggedErrorClass()( "ActivePairingLinksLoadError", @@ -173,7 +172,6 @@ export const BootstrapCredentialError = Schema.Union([ BootstrapCredentialInternalError, ]); export type BootstrapCredentialError = typeof BootstrapCredentialError.Type; -export const isBootstrapCredentialError = Schema.is(BootstrapCredentialError); export interface IssuedBootstrapCredential { readonly id: string; diff --git a/apps/server/src/auth/ServerSecretStore.ts b/apps/server/src/auth/ServerSecretStore.ts index 5e9890c1ea28..4f51604e7389 100644 --- a/apps/server/src/auth/ServerSecretStore.ts +++ b/apps/server/src/auth/ServerSecretStore.ts @@ -149,6 +149,7 @@ export class ServerSecretStore extends Context.Service< } >()("t3/auth/ServerSecretStore") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const crypto = yield* Crypto.Crypto; const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/server/src/auth/SessionStore.ts b/apps/server/src/auth/SessionStore.ts index f4e5e3c487ac..877f1a5bd73e 100644 --- a/apps/server/src/auth/SessionStore.ts +++ b/apps/server/src/auth/SessionStore.ts @@ -349,14 +349,12 @@ export const SessionCredentialInternalError = Schema.Union([ OtherSessionsRevocationError, ]); export type SessionCredentialInternalError = typeof SessionCredentialInternalError.Type; -export const isSessionCredentialInternalError = Schema.is(SessionCredentialInternalError); export const SessionCredentialError = Schema.Union([ SessionCredentialInvalidError, SessionCredentialInternalError, ]); export type SessionCredentialError = typeof SessionCredentialError.Type; -export const isSessionCredentialError = Schema.is(SessionCredentialError); export class SessionStore extends Context.Service< SessionStore, diff --git a/apps/server/src/auth/http.ts b/apps/server/src/auth/http.ts index cc74966c41e2..b50d6eae9a18 100644 --- a/apps/server/src/auth/http.ts +++ b/apps/server/src/auth/http.ts @@ -65,7 +65,7 @@ const appendDpopChallengeOnUnauthorized = (error: EnvironmentAuthInvalidError) = return yield* error; }); -export const currentEnvironmentTraceId = Effect.currentParentSpan.pipe( +const currentEnvironmentTraceId = Effect.currentParentSpan.pipe( Effect.map((span) => span.traceId), Effect.orElseSucceed(() => "unavailable"), ); diff --git a/apps/server/src/background/BackgroundPolicy.ts b/apps/server/src/background/BackgroundPolicy.ts index a2a8e99d33ce..752d6d79b16b 100644 --- a/apps/server/src/background/BackgroundPolicy.ts +++ b/apps/server/src/background/BackgroundPolicy.ts @@ -82,7 +82,7 @@ function leaseKey(lease: Pick, lease: ClientActivityLease, now: DateTime.Utc, @@ -208,6 +208,7 @@ function computeSnapshot(input: { }; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("background.policy.make")(function* () { const hostPowerMonitor = yield* HostPowerMonitor.HostPowerMonitor; const serverSettings = yield* ServerSettingsService; diff --git a/apps/server/src/background/HostPowerMonitor.ts b/apps/server/src/background/HostPowerMonitor.ts index 273548faa47f..3d8c8b35998a 100644 --- a/apps/server/src/background/HostPowerMonitor.ts +++ b/apps/server/src/background/HostPowerMonitor.ts @@ -19,7 +19,7 @@ export class HostPowerMonitor extends Context.Service< } >()("t3/background/HostPowerMonitor") {} -export const makeUnknownSnapshot = ( +const makeUnknownSnapshot = ( source: HostPowerSnapshot["source"], updatedAt: HostPowerSnapshot["updatedAt"], ): HostPowerSnapshot => ({ diff --git a/apps/server/src/checkpointing/CheckpointDiffQuery.ts b/apps/server/src/checkpointing/CheckpointDiffQuery.ts index 077506ff3a84..1520ba0250da 100644 --- a/apps/server/src/checkpointing/CheckpointDiffQuery.ts +++ b/apps/server/src/checkpointing/CheckpointDiffQuery.ts @@ -75,6 +75,7 @@ function buildTurnDiffResult( }; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const projectionSnapshotQuery = yield* ProjectionSnapshotQuery.ProjectionSnapshotQuery; const checkpointStore = yield* CheckpointStore.CheckpointStore; diff --git a/apps/server/src/checkpointing/CheckpointStore.ts b/apps/server/src/checkpointing/CheckpointStore.ts index f1cc596b209d..3d6372526854 100644 --- a/apps/server/src/checkpointing/CheckpointStore.ts +++ b/apps/server/src/checkpointing/CheckpointStore.ts @@ -98,6 +98,7 @@ export class CheckpointStore extends Context.Service< } >()("t3/checkpointing/CheckpointStore") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const vcsRegistry = yield* VcsDriverRegistry.VcsDriverRegistry; diff --git a/apps/server/src/checkpointing/Utils.ts b/apps/server/src/checkpointing/Utils.ts index 50d0163af5a6..adc089f624a8 100644 --- a/apps/server/src/checkpointing/Utils.ts +++ b/apps/server/src/checkpointing/Utils.ts @@ -1,7 +1,7 @@ import * as Encoding from "effect/Encoding"; import { CheckpointRef, ProjectId, type ThreadId } from "@t3tools/contracts"; -export const CHECKPOINT_REFS_PREFIX = "refs/t3/checkpoints"; +const CHECKPOINT_REFS_PREFIX = "refs/t3/checkpoints"; export function checkpointRefForThreadTurn(threadId: ThreadId, turnCount: number): CheckpointRef { return CheckpointRef.make( diff --git a/apps/server/src/cli/app.ts b/apps/server/src/cli/app.ts index 85fbebd74474..1e82486d66ca 100644 --- a/apps/server/src/cli/app.ts +++ b/apps/server/src/cli/app.ts @@ -81,7 +81,7 @@ function isDesktopPlatform(platform: NodeJS.Platform): platform is DesktopAppAct return platform === "darwin" || platform === "linux" || platform === "win32"; } -export function sendDesktopAppActivationRequest(input: { +function sendDesktopAppActivationRequest(input: { readonly address: string; readonly fallbackAddress?: string; readonly request: DesktopAppActivationRequest; diff --git a/apps/server/src/cli/config.ts b/apps/server/src/cli/config.ts index f739a4e2f22c..847edbbc4fe0 100644 --- a/apps/server/src/cli/config.ts +++ b/apps/server/src/cli/config.ts @@ -17,7 +17,7 @@ import { readBootstrapEnvelope } from "../bootstrap.ts"; import * as ServerConfig from "../config.ts"; import { expandHomePath, resolveBaseDir } from "../os-jank.ts"; -export const modeFlag = Flag.choice("mode", ServerConfig.RuntimeMode.literals).pipe( +const modeFlag = Flag.choice("mode", ServerConfig.RuntimeMode.literals).pipe( Flag.withDescription("Runtime mode. `desktop` keeps loopback defaults unless overridden."), Flag.optional, ); @@ -69,7 +69,7 @@ const tailscaleServeFlag = Flag.boolean("tailscale-serve").pipe( ), Flag.optional, ); -export const tailscaleServePortFlag = Flag.integer("tailscale-serve-port").pipe( +const tailscaleServePortFlag = Flag.integer("tailscale-serve-port").pipe( Flag.withSchema(PortSchema), Flag.withDescription("HTTPS port for Tailscale Serve when --tailscale-serve is enabled."), Flag.optional, diff --git a/apps/server/src/cli/pair.ts b/apps/server/src/cli/pair.ts index d40e0d97e484..867c4639a9af 100644 --- a/apps/server/src/cli/pair.ts +++ b/apps/server/src/cli/pair.ts @@ -173,7 +173,7 @@ export const resolveTailscaleLocalTarget = ( return { localPort: state.port }; }; -export const formatPairOutput = (input: { +const formatPairOutput = (input: { readonly serverLabel: string; readonly origin: string; readonly pairingUrl: string; diff --git a/apps/server/src/cloud/CliTokenManager.ts b/apps/server/src/cloud/CliTokenManager.ts index 8c3869accc76..979a63ec67a6 100644 --- a/apps/server/src/cloud/CliTokenManager.ts +++ b/apps/server/src/cloud/CliTokenManager.ts @@ -324,6 +324,7 @@ export const outOfBandOAuthLogin = Effect.fn("cloud.cli_token.out_of_band_oauth_ }); }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { // Capture exactly the services the login/refresh flows need at build time // (matching the behavior before the out-of-band flow captured the instances), not diff --git a/apps/server/src/cloud/ManagedEndpointRuntime.ts b/apps/server/src/cloud/ManagedEndpointRuntime.ts index 564d7346d036..0556695f9dc2 100644 --- a/apps/server/src/cloud/ManagedEndpointRuntime.ts +++ b/apps/server/src/cloud/ManagedEndpointRuntime.ts @@ -111,6 +111,7 @@ const stopConnector = (connector: ActiveConnector | null) => ) : Effect.void; +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; const relayClient = yield* RelayClient.RelayClient; diff --git a/apps/server/src/cloud/publicConfig.ts b/apps/server/src/cloud/publicConfig.ts index e977d7cfdf0d..d60a09b6decb 100644 --- a/apps/server/src/cloud/publicConfig.ts +++ b/apps/server/src/cloud/publicConfig.ts @@ -49,21 +49,21 @@ function normalizeSecureUrl(value: string): string | null { } } -export const buildTimeRelayUrl = +const buildTimeRelayUrl = typeof __T3CODE_BUILD_RELAY_URL__ === "undefined" ? "" : (normalizeSecureRelayUrl(__T3CODE_BUILD_RELAY_URL__) ?? ""); -export const buildTimeClerkPublishableKey = readBuildTimeValue( +const buildTimeClerkPublishableKey = readBuildTimeValue( typeof __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__ === "undefined" ? undefined : __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__, ); -export const buildTimeClerkCliOAuthClientId = readBuildTimeValue( +const buildTimeClerkCliOAuthClientId = readBuildTimeValue( typeof __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__ === "undefined" ? undefined : __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__, ); -export const buildTimeRelayClientTracing = { +const buildTimeRelayClientTracing = { tracesUrl: readBuildTimeValue( typeof __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_URL__ === "undefined" ? undefined diff --git a/apps/server/src/cloud/serviceProtocol.ts b/apps/server/src/cloud/serviceProtocol.ts index af94c9b4b5c0..bb61866a93ff 100644 --- a/apps/server/src/cloud/serviceProtocol.ts +++ b/apps/server/src/cloud/serviceProtocol.ts @@ -71,7 +71,7 @@ export const isExactServiceVersion = (version: string): boolean => const isRecord = (value: unknown): value is Record => typeof value === "object" && value !== null && !Array.isArray(value); -export function decodeServiceUpdate(value: unknown): ServiceUpdateRecord | undefined { +function decodeServiceUpdate(value: unknown): ServiceUpdateRecord | undefined { if (!isRecord(value)) return undefined; const { id, fromVersion, targetVersion, status } = value; if ( diff --git a/apps/server/src/desktopUpdate/DesktopAppUpdate.ts b/apps/server/src/desktopUpdate/DesktopAppUpdate.ts index 1e7b54b2474b..9c5d88bd7910 100644 --- a/apps/server/src/desktopUpdate/DesktopAppUpdate.ts +++ b/apps/server/src/desktopUpdate/DesktopAppUpdate.ts @@ -25,7 +25,7 @@ const DESKTOP_INSTALL_TIMEOUT = Duration.minutes(2); /** Progress stage a desktop update state maps to, or null when the state carries no progress worth streaming. */ -export function desktopUpdateProgressStage( +function desktopUpdateProgressStage( state: DesktopUpdateState, ): ServerSelfUpdateProgressStage | null { switch (state.status) { diff --git a/apps/server/src/diagnostics/ProcessDiagnostics.ts b/apps/server/src/diagnostics/ProcessDiagnostics.ts index fecf457046d9..82ea3c074206 100644 --- a/apps/server/src/diagnostics/ProcessDiagnostics.ts +++ b/apps/server/src/diagnostics/ProcessDiagnostics.ts @@ -54,6 +54,7 @@ function canSignalCategory(category: ResourceTelemetryProcessCategory): boolean ); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("makeProcessDiagnostics")(function* () { const telemetry = yield* ResourceTelemetry.ResourceTelemetry; const refreshedTelemetry = telemetry.refresh.pipe(Effect.catch(() => telemetry.latest)); diff --git a/apps/server/src/diagnostics/ProcessResourceMonitor.ts b/apps/server/src/diagnostics/ProcessResourceMonitor.ts index 5f5e32dd28da..de5f13ba83da 100644 --- a/apps/server/src/diagnostics/ProcessResourceMonitor.ts +++ b/apps/server/src/diagnostics/ProcessResourceMonitor.ts @@ -28,6 +28,7 @@ function isLegacyBackendCategory(category: ResourceTelemetryProcessCategory): bo ); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("makeProcessResourceMonitor")(function* () { const telemetry = yield* ResourceTelemetry.ResourceTelemetry; const readHistory: ProcessResourceMonitor["Service"]["readHistory"] = (input) => diff --git a/apps/server/src/diagnostics/TraceDiagnostics.ts b/apps/server/src/diagnostics/TraceDiagnostics.ts index d54e033380c0..35c18fe7d802 100644 --- a/apps/server/src/diagnostics/TraceDiagnostics.ts +++ b/apps/server/src/diagnostics/TraceDiagnostics.ts @@ -411,6 +411,7 @@ function readTraceFile( ); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/server/src/environment/RemoteOpenTargets.ts b/apps/server/src/environment/RemoteOpenTargets.ts index f70dfa68aaab..2b280ebbd6d8 100644 --- a/apps/server/src/environment/RemoteOpenTargets.ts +++ b/apps/server/src/environment/RemoteOpenTargets.ts @@ -26,6 +26,7 @@ export class RemoteOpenTargets extends Context.Service< } >()("t3/environment/RemoteOpenTargets") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; const net = yield* NetService.NetService; diff --git a/apps/server/src/environment/ServerEnvironment.ts b/apps/server/src/environment/ServerEnvironment.ts index 0b7f1761cf76..17fb7ddd6730 100644 --- a/apps/server/src/environment/ServerEnvironment.ts +++ b/apps/server/src/environment/ServerEnvironment.ts @@ -179,6 +179,7 @@ const makeIdentity = Effect.gen(function* () { }); }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const path = yield* Path.Path; const serverConfig = yield* ServerConfig.ServerConfig; diff --git a/apps/server/src/git/GitWorkflowService.ts b/apps/server/src/git/GitWorkflowService.ts index c9b4a4cca365..854d513a6120 100644 --- a/apps/server/src/git/GitWorkflowService.ts +++ b/apps/server/src/git/GitWorkflowService.ts @@ -142,6 +142,7 @@ function nonRepositoryListRefs(): VcsListRefsResult { }; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const registry = yield* VcsDriverRegistry.VcsDriverRegistry; const git = yield* GitVcsDriver.GitVcsDriver; diff --git a/apps/server/src/imageMime.ts b/apps/server/src/imageMime.ts index 66ce6096e853..1129edfd3ef1 100644 --- a/apps/server/src/imageMime.ts +++ b/apps/server/src/imageMime.ts @@ -1,6 +1,6 @@ import Mime from "@effect/platform-node/Mime"; -export const IMAGE_EXTENSION_BY_MIME_TYPE: Record = { +const IMAGE_EXTENSION_BY_MIME_TYPE: Record = { "image/avif": ".avif", "image/bmp": ".bmp", "image/gif": ".gif", diff --git a/apps/server/src/mcp/toolkits/preview/handlers.ts b/apps/server/src/mcp/toolkits/preview/handlers.ts index c501ee08711d..b107b8450a72 100644 --- a/apps/server/src/mcp/toolkits/preview/handlers.ts +++ b/apps/server/src/mcp/toolkits/preview/handlers.ts @@ -104,5 +104,3 @@ export const PreviewStandardToolkitHandlersLive = PreviewStandardToolkit.toLayer export const PreviewSnapshotToolkitHandlersLive = PreviewSnapshotToolkit.toLayer({ preview_snapshot, }); - -export const PreviewToolkitHandlersLive = PreviewToolkit.toLayer(handlers); diff --git a/apps/server/src/mcp/toolkits/preview/tools.ts b/apps/server/src/mcp/toolkits/preview/tools.ts index ab8d1580bb61..3d644a31d9a8 100644 --- a/apps/server/src/mcp/toolkits/preview/tools.ts +++ b/apps/server/src/mcp/toolkits/preview/tools.ts @@ -45,7 +45,7 @@ const safeBrowserTool = (tool: T): T => const readonlyBrowserTool = (tool: T): T => safeBrowserTool(tool).annotate(Tool.Readonly, true).annotate(Tool.Idempotent, true) as T; -export const PreviewStatusTool = Tool.make("preview_status", { +const PreviewStatusTool = Tool.make("preview_status", { description: "Report whether a collaborative browser tab is automation-capable, including its URL, title, visibility, loading state, viewport mode, and measured CSS-pixel size. Pass tabId to inspect a specific tab; omit it to use this agent session's current tab.", parameters: PreviewAutomationTabTargetInput, @@ -58,7 +58,7 @@ export const PreviewStatusTool = Tool.make("preview_status", { .annotate(Tool.Destructive, false) .annotate(Tool.Idempotent, true); -export const PreviewOpenTool = browserTool( +const PreviewOpenTool = browserTool( Tool.make("preview_open", { description: "Initialize a collaborative browser tab and open its thread-bound inline preview by default. Set open=false for background-only automation. Pass tabId to reuse a specific existing tab, set reuseExistingTab=false to create another tab, or omit both to use this agent session's current tab.", @@ -71,7 +71,7 @@ export const PreviewOpenTool = browserTool( .annotate(Tool.Destructive, false), ); -export const PreviewNavigateTool = safeBrowserTool( +const PreviewNavigateTool = safeBrowserTool( Tool.make("preview_navigate", { description: "Navigate a collaborative browser tab. Pass tabId to target a specific tab, plus {url:'https://t3.chat'} for a website or {target:{kind:'environment-port',port:5173}} for a dev server. Exactly one of url or target is required.", @@ -82,7 +82,7 @@ export const PreviewNavigateTool = safeBrowserTool( }).annotate(Tool.Title, "Navigate browser preview"), ); -export const PreviewResizeTool = safeBrowserTool( +const PreviewResizeTool = safeBrowserTool( Tool.make("preview_resize", { description: "Resize a collaborative browser tab, optionally selected by tabId. Use {mode:'fill'}, {mode:'freeform',width:1024,height:768}, or {mode:'preset',preset:'iphone-12-pro',orientation:'portrait'}. This changes CSS layout breakpoints without changing the desktop browser user agent.", @@ -95,7 +95,7 @@ export const PreviewResizeTool = safeBrowserTool( .annotate(Tool.Idempotent, true), ); -export const PreviewSetAppearanceTool = safeBrowserTool( +const PreviewSetAppearanceTool = safeBrowserTool( Tool.make("preview_set_appearance", { description: "Emulate prefers-color-scheme in a collaborative browser tab, optionally selected by tabId. Use {colorScheme:'dark'} or {colorScheme:'light'} to preview the page in that appearance, and {colorScheme:'system'} to clear the override and follow the OS appearance.", @@ -127,7 +127,7 @@ export const PreviewSnapshotTool = readonlyBrowserTool( }).annotate(Tool.Title, "Inspect browser page"), ); -export const PreviewClickTool = browserTool( +const PreviewClickTool = browserTool( Tool.make("preview_click", { description: "Click exactly one target in the tab selected by tabId, or this agent session's current tab when omitted. Prefer a Playwright locator; selector accepts legacy CSS; x and y must be supplied together.", @@ -138,7 +138,7 @@ export const PreviewClickTool = browserTool( }).annotate(Tool.Title, "Click preview page"), ); -export const PreviewTypeTool = browserTool( +const PreviewTypeTool = browserTool( Tool.make("preview_type", { description: "Insert literal text into one input in the tab selected by tabId, or this agent session's current tab when omitted. Prefer a Playwright locator; set clear=true to replace existing text.", @@ -149,7 +149,7 @@ export const PreviewTypeTool = browserTool( }).annotate(Tool.Title, "Type into preview page"), ); -export const PreviewPressTool = browserTool( +const PreviewPressTool = browserTool( Tool.make("preview_press", { description: "Press one keyboard key in the tab selected by tabId, or this agent session's current tab when omitted. Examples: {key:'Enter'}, {key:'Escape'}, or {key:'a',modifiers:['Meta']}.", @@ -160,7 +160,7 @@ export const PreviewPressTool = browserTool( }).annotate(Tool.Title, "Press key in preview page"), ); -export const PreviewScrollTool = safeBrowserTool( +const PreviewScrollTool = safeBrowserTool( Tool.make("preview_scroll", { description: "Scroll the tab selected by tabId, or this agent session's current tab when omitted. Positive deltaY scrolls down and positive deltaX scrolls right; a locator/selector targets a container.", @@ -171,7 +171,7 @@ export const PreviewScrollTool = safeBrowserTool( }).annotate(Tool.Title, "Scroll preview page"), ); -export const PreviewEvaluateTool = browserTool( +const PreviewEvaluateTool = browserTool( Tool.make("preview_evaluate", { description: "Evaluate JavaScript in the tab selected by tabId, or this agent session's current tab when omitted. Returns a serializable result up to 64 KB; the expression may mutate page state.", @@ -182,7 +182,7 @@ export const PreviewEvaluateTool = browserTool( }).annotate(Tool.Title, "Evaluate JavaScript in preview"), ); -export const PreviewWaitForTool = readonlyBrowserTool( +const PreviewWaitForTool = readonlyBrowserTool( Tool.make("preview_wait_for", { description: "Wait in the tab selected by tabId, or this agent session's current tab when omitted, until all supplied locator, selector, text, and URL conditions match.", @@ -193,7 +193,7 @@ export const PreviewWaitForTool = readonlyBrowserTool( }).annotate(Tool.Title, "Wait for preview page condition"), ); -export const PreviewRecordingStartTool = safeBrowserTool( +const PreviewRecordingStartTool = safeBrowserTool( Tool.make("preview_recording_start", { description: "Start recording the collaborative browser tab selected by tabId, or this agent session's current tab when omitted.", @@ -204,7 +204,7 @@ export const PreviewRecordingStartTool = safeBrowserTool( }).annotate(Tool.Title, "Start browser recording"), ); -export const PreviewRecordingStopTool = safeBrowserTool( +const PreviewRecordingStopTool = safeBrowserTool( Tool.make("preview_recording_stop", { description: "Stop recording the collaborative browser tab selected by tabId, or this agent session's current tab when omitted, and save it as a local evidence artifact.", diff --git a/apps/server/src/observability/BrowserTraceCollector.ts b/apps/server/src/observability/BrowserTraceCollector.ts index 300a50fe3308..694c52d99aa2 100644 --- a/apps/server/src/observability/BrowserTraceCollector.ts +++ b/apps/server/src/observability/BrowserTraceCollector.ts @@ -10,6 +10,7 @@ export class BrowserTraceCollector extends Context.Service< } >()("t3/observability/BrowserTraceCollector") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = (sink: TraceSink): BrowserTraceCollector["Service"] => BrowserTraceCollector.of({ record: (records) => diff --git a/apps/server/src/orchestration/Errors.ts b/apps/server/src/orchestration/Errors.ts index dc29dcbfa6f8..3d634579e392 100644 --- a/apps/server/src/orchestration/Errors.ts +++ b/apps/server/src/orchestration/Errors.ts @@ -126,13 +126,6 @@ export type OrchestrationEngineError = | OrchestrationCommandJsonParseError | OrchestrationCommandDecodeError; -export function toOrchestrationCommandDecodeError(error: Schema.SchemaError) { - return new OrchestrationCommandDecodeError({ - issue: SchemaIssue.makeFormatterDefault()(error.issue), - cause: error, - }); -} - export function toProjectorDecodeError(eventType: string) { return (error: Schema.SchemaError): OrchestrationProjectorDecodeError => new OrchestrationProjectorDecodeError({ @@ -141,19 +134,3 @@ export function toProjectorDecodeError(eventType: string) { cause: error, }); } - -export function toOrchestrationJsonParseError(cause: unknown) { - return new OrchestrationCommandJsonParseError({ - detail: `Failed to parse orchestration command JSON`, - cause, - }); -} - -export function toListenerCallbackError(listener: "read-model" | "domain-event") { - return (cause: unknown): OrchestrationListenerCallbackError => - new OrchestrationListenerCallbackError({ - listener, - detail: `Failed to invoke orchestration ${listener} listener`, - cause, - }); -} diff --git a/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts b/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts index 5f82a26e2a36..8a0f4186a831 100644 --- a/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts +++ b/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts @@ -7,6 +7,7 @@ import { MessageId, NonNegativeInt, OrchestrationCheckpointFile, + OrchestrationCheckpointStatus, OrchestrationProposedPlanId, OrchestrationReadModel, OrchestrationThreadSearchSource, @@ -46,7 +47,6 @@ import { toPersistenceSqlError, type ProjectionRepositoryError, } from "../../persistence/Errors.ts"; -import { ProjectionCheckpoint } from "../../persistence/Services/ProjectionCheckpoints.ts"; import { ThreadBackgroundLivenessService } from "../ThreadBackgroundLiveness.ts"; import { ThreadPlanProgressService } from "../ThreadPlanProgress.ts"; import { ProjectionProject } from "../../persistence/Services/ProjectionProjects.ts"; @@ -134,11 +134,16 @@ const ProjectionThreadRuntimeContextDbRowSchema = Schema.Struct({ title: Schema.String, session: Schema.NullOr(ProjectionThreadSessionDbRowSchema), }); -const ProjectionCheckpointDbRowSchema = ProjectionCheckpoint.mapFields( - Struct.assign({ - files: Schema.fromJsonString(Schema.Array(OrchestrationCheckpointFile)), - }), -); +const ProjectionCheckpointDbRowSchema = Schema.Struct({ + threadId: ThreadId, + turnId: TurnId, + checkpointTurnCount: NonNegativeInt, + checkpointRef: CheckpointRef, + status: OrchestrationCheckpointStatus, + files: Schema.fromJsonString(Schema.Array(OrchestrationCheckpointFile)), + assistantMessageId: Schema.NullOr(MessageId), + completedAt: IsoDateTime, +}); const ProjectionLatestTurnDbRowSchema = Schema.Struct({ threadId: ProjectionThread.fields.threadId, turnId: TurnId, diff --git a/apps/server/src/orchestration/LiveStreamBudget.ts b/apps/server/src/orchestration/LiveStreamBudget.ts index e86127b2b2df..5a3a08e7e4b3 100644 --- a/apps/server/src/orchestration/LiveStreamBudget.ts +++ b/apps/server/src/orchestration/LiveStreamBudget.ts @@ -6,8 +6,8 @@ import * as Exit from "effect/Exit"; import * as Scope from "effect/Scope"; import * as Stream from "effect/Stream"; -export const LIVE_STREAM_MAX_ITEMS = 1_000; -export const LIVE_STREAM_MAX_SERIALIZED_BYTES = 8 * 1024 * 1024; +const LIVE_STREAM_MAX_ITEMS = 1_000; +const LIVE_STREAM_MAX_SERIALIZED_BYTES = 8 * 1024 * 1024; export interface RetainedLiveItem { readonly value: A; diff --git a/apps/server/src/orchestration/ThreadPullRequestReactor.ts b/apps/server/src/orchestration/ThreadPullRequestReactor.ts index 6e2aa0b3e054..7da26de78a44 100644 --- a/apps/server/src/orchestration/ThreadPullRequestReactor.ts +++ b/apps/server/src/orchestration/ThreadPullRequestReactor.ts @@ -77,6 +77,7 @@ export function pullRequestMatchesProject( ); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const engine = yield* OrchestrationEngine.OrchestrationEngineService; const snapshots = yield* ProjectionSnapshotQuery.ProjectionSnapshotQuery; diff --git a/apps/server/src/orchestration/ThreadSettlementPolicy.ts b/apps/server/src/orchestration/ThreadSettlementPolicy.ts index 7c55fa37d1f3..1df7855d1e04 100644 --- a/apps/server/src/orchestration/ThreadSettlementPolicy.ts +++ b/apps/server/src/orchestration/ThreadSettlementPolicy.ts @@ -8,7 +8,7 @@ export interface SettlementPullRequest { } const DAY_MS = 24 * 60 * 60 * 1_000; -export const QUEUED_TURN_START_GRACE_MS = 2 * 60 * 1_000; +const QUEUED_TURN_START_GRACE_MS = 2 * 60 * 1_000; function latestTimestamp(values: ReadonlyArray): string | null { let latest: string | null = null; diff --git a/apps/server/src/orchestration/ThreadSettlementReactor.ts b/apps/server/src/orchestration/ThreadSettlementReactor.ts index 4830ec9d80e5..480dd56ab354 100644 --- a/apps/server/src/orchestration/ThreadSettlementReactor.ts +++ b/apps/server/src/orchestration/ThreadSettlementReactor.ts @@ -32,6 +32,7 @@ export class ThreadSettlementReactor extends Context.Service< } >()("t3/orchestration/ThreadSettlementReactor") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const engine = yield* OrchestrationEngine.OrchestrationEngineService; const snapshots = yield* ProjectionSnapshotQuery.ProjectionSnapshotQuery; diff --git a/apps/server/src/orchestration/commandInvariants.ts b/apps/server/src/orchestration/commandInvariants.ts index 110a499d37c9..873eab007bea 100644 --- a/apps/server/src/orchestration/commandInvariants.ts +++ b/apps/server/src/orchestration/commandInvariants.ts @@ -25,7 +25,7 @@ function findThreadById( return readModel.threads.find((thread) => thread.id === threadId); } -export function findProjectById( +function findProjectById( readModel: OrchestrationReadModel, projectId: ProjectId, ): OrchestrationProject | undefined { diff --git a/apps/server/src/orchestration/runtimeLayer.ts b/apps/server/src/orchestration/runtimeLayer.ts index 779042e2f685..ea02e5e2ebf9 100644 --- a/apps/server/src/orchestration/runtimeLayer.ts +++ b/apps/server/src/orchestration/runtimeLayer.ts @@ -8,16 +8,16 @@ import { OrchestrationProjectionSnapshotQueryLive } from "./Layers/ProjectionSna import * as ThreadBackgroundLiveness from "./ThreadBackgroundLiveness.ts"; import * as ThreadPlanProgress from "./ThreadPlanProgress.ts"; -export const OrchestrationEventInfrastructureLayerLive = Layer.mergeAll( +const OrchestrationEventInfrastructureLayerLive = Layer.mergeAll( OrchestrationEventStoreLive, OrchestrationCommandReceiptRepositoryLive, ); -export const OrchestrationProjectionPipelineLayerLive = OrchestrationProjectionPipelineLive.pipe( +const OrchestrationProjectionPipelineLayerLive = OrchestrationProjectionPipelineLive.pipe( Layer.provide(OrchestrationEventStoreLive), ); -export const OrchestrationInfrastructureLayerLive = Layer.mergeAll( +const OrchestrationInfrastructureLayerLive = Layer.mergeAll( OrchestrationProjectionSnapshotQueryLive, OrchestrationEventInfrastructureLayerLive, OrchestrationProjectionPipelineLayerLive, diff --git a/apps/server/src/persistence/AuthPairingLinks.ts b/apps/server/src/persistence/AuthPairingLinks.ts index e54c977e7ab7..94b43a7e3003 100644 --- a/apps/server/src/persistence/AuthPairingLinks.ts +++ b/apps/server/src/persistence/AuthPairingLinks.ts @@ -119,6 +119,7 @@ function toPersistenceSqlOrDecodeError( }); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const sql = yield* SqlClient.SqlClient; diff --git a/apps/server/src/persistence/AuthSessions.ts b/apps/server/src/persistence/AuthSessions.ts index aebbb839e5ce..ef1d170f39de 100644 --- a/apps/server/src/persistence/AuthSessions.ts +++ b/apps/server/src/persistence/AuthSessions.ts @@ -200,6 +200,7 @@ function toPersistenceSqlOrDecodeError( }); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const sql = yield* SqlClient.SqlClient; diff --git a/apps/server/src/persistence/Layers/ProjectionCheckpoints.ts b/apps/server/src/persistence/Layers/ProjectionCheckpoints.ts deleted file mode 100644 index cfa5658d0e9c..000000000000 --- a/apps/server/src/persistence/Layers/ProjectionCheckpoints.ts +++ /dev/null @@ -1,217 +0,0 @@ -import { OrchestrationCheckpointFile } from "@t3tools/contracts"; -import * as SqlClient from "effect/unstable/sql/SqlClient"; -import * as SqlSchema from "effect/unstable/sql/SqlSchema"; -import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; -import * as Option from "effect/Option"; -import * as Schema from "effect/Schema"; -import * as Struct from "effect/Struct"; - -import { toPersistenceDecodeError, toPersistenceSqlError } from "../Errors.ts"; -import { - DeleteByThreadIdInput, - GetByThreadAndTurnCountInput, - ListByThreadIdInput, - ProjectionCheckpoint, - ProjectionCheckpointRepository, - type ProjectionCheckpointRepositoryShape, -} from "../Services/ProjectionCheckpoints.ts"; - -const ProjectionCheckpointDbRowSchema = ProjectionCheckpoint.mapFields( - Struct.assign({ - files: Schema.fromJsonString(Schema.Array(OrchestrationCheckpointFile)), - }), -); - -function toPersistenceSqlOrDecodeError(sqlOperation: string, decodeOperation: string) { - return (cause: unknown) => - Schema.isSchemaError(cause) - ? toPersistenceDecodeError(decodeOperation)(cause) - : toPersistenceSqlError(sqlOperation)(cause); -} - -const makeProjectionCheckpointRepository = Effect.gen(function* () { - const sql = yield* SqlClient.SqlClient; - - const clearCheckpointConflict = SqlSchema.void({ - Request: GetByThreadAndTurnCountInput, - execute: ({ threadId, checkpointTurnCount }) => - sql` - UPDATE projection_turns - SET - checkpoint_turn_count = NULL, - checkpoint_ref = NULL, - checkpoint_status = NULL, - checkpoint_files_json = '[]' - WHERE thread_id = ${threadId} - AND checkpoint_turn_count = ${checkpointTurnCount} - `, - }); - - const upsertProjectionCheckpointRow = SqlSchema.void({ - Request: ProjectionCheckpointDbRowSchema, - execute: (row) => - sql` - INSERT INTO projection_turns ( - thread_id, - turn_id, - pending_message_id, - assistant_message_id, - state, - requested_at, - started_at, - completed_at, - checkpoint_turn_count, - checkpoint_ref, - checkpoint_status, - checkpoint_files_json - ) - VALUES ( - ${row.threadId}, - ${row.turnId}, - NULL, - ${row.assistantMessageId}, - ${row.status === "error" ? "error" : "completed"}, - ${row.completedAt}, - ${row.completedAt}, - ${row.completedAt}, - ${row.checkpointTurnCount}, - ${row.checkpointRef}, - ${row.status}, - ${row.files} - ) - ON CONFLICT (thread_id, turn_id) - DO UPDATE SET - assistant_message_id = excluded.assistant_message_id, - state = excluded.state, - completed_at = excluded.completed_at, - checkpoint_turn_count = excluded.checkpoint_turn_count, - checkpoint_ref = excluded.checkpoint_ref, - checkpoint_status = excluded.checkpoint_status, - checkpoint_files_json = excluded.checkpoint_files_json - `, - }); - - const listProjectionCheckpointRows = SqlSchema.findAll({ - Request: ListByThreadIdInput, - Result: ProjectionCheckpointDbRowSchema, - execute: ({ threadId }) => - sql` - SELECT - thread_id AS "threadId", - turn_id AS "turnId", - checkpoint_turn_count AS "checkpointTurnCount", - checkpoint_ref AS "checkpointRef", - checkpoint_status AS "status", - checkpoint_files_json AS "files", - assistant_message_id AS "assistantMessageId", - completed_at AS "completedAt" - FROM projection_turns - WHERE thread_id = ${threadId} - AND checkpoint_turn_count IS NOT NULL - ORDER BY checkpoint_turn_count ASC - `, - }); - - const getProjectionCheckpointRow = SqlSchema.findOneOption({ - Request: GetByThreadAndTurnCountInput, - Result: ProjectionCheckpointDbRowSchema, - execute: ({ threadId, checkpointTurnCount }) => - sql` - SELECT - thread_id AS "threadId", - turn_id AS "turnId", - checkpoint_turn_count AS "checkpointTurnCount", - checkpoint_ref AS "checkpointRef", - checkpoint_status AS "status", - checkpoint_files_json AS "files", - assistant_message_id AS "assistantMessageId", - completed_at AS "completedAt" - FROM projection_turns - WHERE thread_id = ${threadId} - AND checkpoint_turn_count = ${checkpointTurnCount} - `, - }); - - const deleteProjectionCheckpointRows = SqlSchema.void({ - Request: DeleteByThreadIdInput, - execute: ({ threadId }) => - sql` - UPDATE projection_turns - SET - checkpoint_turn_count = NULL, - checkpoint_ref = NULL, - checkpoint_status = NULL, - checkpoint_files_json = '[]' - WHERE thread_id = ${threadId} - AND checkpoint_turn_count IS NOT NULL - `, - }); - - const upsertCheckpointRow = (row: Schema.Schema.Type) => - sql.withTransaction( - clearCheckpointConflict({ - threadId: row.threadId, - checkpointTurnCount: row.checkpointTurnCount, - }).pipe(Effect.flatMap(() => upsertProjectionCheckpointRow(row))), - ); - - const upsert: ProjectionCheckpointRepositoryShape["upsert"] = (row) => - upsertCheckpointRow(row).pipe( - Effect.mapError( - toPersistenceSqlOrDecodeError( - "ProjectionCheckpointRepository.upsert:query", - "ProjectionCheckpointRepository.upsert:encodeRequest", - ), - ), - ); - - const listByThreadId: ProjectionCheckpointRepositoryShape["listByThreadId"] = (input) => - listProjectionCheckpointRows(input).pipe( - Effect.mapError( - toPersistenceSqlOrDecodeError( - "ProjectionCheckpointRepository.listByThreadId:query", - "ProjectionCheckpointRepository.listByThreadId:decodeRows", - ), - ), - Effect.map((rows) => rows as ReadonlyArray>), - ); - - const getByThreadAndTurnCount: ProjectionCheckpointRepositoryShape["getByThreadAndTurnCount"] = ( - input, - ) => - getProjectionCheckpointRow(input).pipe( - Effect.mapError( - toPersistenceSqlOrDecodeError( - "ProjectionCheckpointRepository.getByThreadAndTurnCount:query", - "ProjectionCheckpointRepository.getByThreadAndTurnCount:decodeRow", - ), - ), - Effect.flatMap((rowOption) => - Option.match(rowOption, { - onNone: () => Effect.succeed(Option.none()), - onSome: (row) => - Effect.succeed(Option.some(row as Schema.Schema.Type)), - }), - ), - ); - - const deleteByThreadId: ProjectionCheckpointRepositoryShape["deleteByThreadId"] = (input) => - deleteProjectionCheckpointRows(input).pipe( - Effect.mapError( - toPersistenceSqlError("ProjectionCheckpointRepository.deleteByThreadId:query"), - ), - ); - - return { - upsert, - listByThreadId, - getByThreadAndTurnCount, - deleteByThreadId, - } satisfies ProjectionCheckpointRepositoryShape; -}); - -export const ProjectionCheckpointRepositoryLive = Layer.effect( - ProjectionCheckpointRepository, - makeProjectionCheckpointRepository, -); diff --git a/apps/server/src/persistence/Migrations.ts b/apps/server/src/persistence/Migrations.ts index c95f746d3648..bc176f62cc3c 100644 --- a/apps/server/src/persistence/Migrations.ts +++ b/apps/server/src/persistence/Migrations.ts @@ -72,7 +72,7 @@ import Migration0049 from "./Migrations/049_ProjectionThreadsActiveOrderKey.ts"; * Uses Migrator.fromRecord which parses the key format and * returns migrations sorted by ID. */ -export const migrationEntries = [ +const migrationEntries = [ [1, "OrchestrationEvents", Migration0001], [2, "OrchestrationCommandReceipts", Migration0002], [3, "CheckpointDiffBlobs", Migration0003], @@ -126,7 +126,7 @@ export const migrationEntries = [ export const migrationManifest = migrationEntries.map(([id, name]) => [id, name] as const); -export const makeMigrationLoader = (throughId?: number) => +const makeMigrationLoader = (throughId?: number) => Migrator.fromRecord( Object.fromEntries( migrationEntries diff --git a/apps/server/src/persistence/ProviderSessionRuntime.ts b/apps/server/src/persistence/ProviderSessionRuntime.ts index d73f56aab9e0..bc66b438b6c6 100644 --- a/apps/server/src/persistence/ProviderSessionRuntime.ts +++ b/apps/server/src/persistence/ProviderSessionRuntime.ts @@ -166,6 +166,7 @@ function toPersistenceSqlOrDecodeError( }); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const sql = yield* SqlClient.SqlClient; diff --git a/apps/server/src/persistence/Services/ProjectionCheckpoints.ts b/apps/server/src/persistence/Services/ProjectionCheckpoints.ts deleted file mode 100644 index 7796ebec2a88..000000000000 --- a/apps/server/src/persistence/Services/ProjectionCheckpoints.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** - * ProjectionCheckpointRepository - Projection repository interface for checkpoints. - * - * Owns persistence operations for projected checkpoint summaries in thread - * timelines. - * - * @module ProjectionCheckpointRepository - */ -import { - CheckpointRef, - IsoDateTime, - MessageId, - NonNegativeInt, - OrchestrationCheckpointFile, - OrchestrationCheckpointStatus, - ThreadId, - TurnId, -} from "@t3tools/contracts"; -import * as Option from "effect/Option"; -import * as Context from "effect/Context"; -import * as Schema from "effect/Schema"; -import type * as Effect from "effect/Effect"; - -import type { ProjectionRepositoryError } from "../Errors.ts"; - -export const ProjectionCheckpoint = Schema.Struct({ - threadId: ThreadId, - turnId: TurnId, - checkpointTurnCount: NonNegativeInt, - checkpointRef: CheckpointRef, - status: OrchestrationCheckpointStatus, - files: Schema.Array(OrchestrationCheckpointFile), - assistantMessageId: Schema.NullOr(MessageId), - completedAt: IsoDateTime, -}); -export type ProjectionCheckpoint = typeof ProjectionCheckpoint.Type; - -export const ListByThreadIdInput = Schema.Struct({ - threadId: ThreadId, -}); -export type ListByThreadIdInput = typeof ListByThreadIdInput.Type; - -export const GetByThreadAndTurnCountInput = Schema.Struct({ - threadId: ThreadId, - checkpointTurnCount: NonNegativeInt, -}); -export type GetByThreadAndTurnCountInput = typeof GetByThreadAndTurnCountInput.Type; - -export const DeleteByThreadIdInput = Schema.Struct({ - threadId: ThreadId, -}); -export type DeleteByThreadIdInput = typeof DeleteByThreadIdInput.Type; - -/** - * ProjectionCheckpointRepositoryShape - Service API for projected checkpoints. - */ -export interface ProjectionCheckpointRepositoryShape { - /** - * Insert or replace a projected checkpoint row. - * - * Upserts by composite key `(threadId, checkpointTurnCount)`. - */ - readonly upsert: (row: ProjectionCheckpoint) => Effect.Effect; - - /** - * List projected checkpoints for a thread. - * - * Returned in ascending checkpoint turn-count order. - */ - readonly listByThreadId: ( - input: ListByThreadIdInput, - ) => Effect.Effect, ProjectionRepositoryError>; - - /** - * Read a projected checkpoint by thread and turn-count key. - */ - readonly getByThreadAndTurnCount: ( - input: GetByThreadAndTurnCountInput, - ) => Effect.Effect, ProjectionRepositoryError>; - - /** - * Delete projected checkpoint rows by thread. - */ - readonly deleteByThreadId: ( - input: DeleteByThreadIdInput, - ) => Effect.Effect; -} - -/** - * ProjectionCheckpointRepository - Service tag for checkpoint projection persistence. - */ -export class ProjectionCheckpointRepository extends Context.Service< - ProjectionCheckpointRepository, - ProjectionCheckpointRepositoryShape ->()("t3/persistence/Services/ProjectionCheckpoints/ProjectionCheckpointRepository") {} diff --git a/apps/server/src/preview/Manager.ts b/apps/server/src/preview/Manager.ts index 3c0169eba40a..d462b6a19c60 100644 --- a/apps/server/src/preview/Manager.ts +++ b/apps/server/src/preview/Manager.ts @@ -153,6 +153,7 @@ const buildIdleSnapshot = (input: { updatedAt: input.updatedAt, }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* PreviewManagerMake() { const serverEpoch = NodeCrypto.randomUUID(); const stateRef = yield* SynchronizedRef.make(initialState); diff --git a/apps/server/src/preview/PortScanner.ts b/apps/server/src/preview/PortScanner.ts index 4571aeef4c6b..d179bcb8f690 100644 --- a/apps/server/src/preview/PortScanner.ts +++ b/apps/server/src/preview/PortScanner.ts @@ -289,6 +289,7 @@ const serversEqual = ( return true; }; +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* PortDiscoveryMake() { const net = yield* Net.NetService; const processRunner = yield* ProcessRunner.ProcessRunner; diff --git a/apps/server/src/process/externalLauncher.ts b/apps/server/src/process/externalLauncher.ts index 184c8b519a96..4e50a5e72339 100644 --- a/apps/server/src/process/externalLauncher.ts +++ b/apps/server/src/process/externalLauncher.ts @@ -752,6 +752,7 @@ const launchEditorProcess = Effect.fn("externalLauncher.launchEditorProcess")(fu ); }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/server/src/processRunner.ts b/apps/server/src/processRunner.ts index c245b0411525..b4619a05ec23 100644 --- a/apps/server/src/processRunner.ts +++ b/apps/server/src/processRunner.ts @@ -402,6 +402,7 @@ const runProcessCore = Effect.fn("processRunner.runProcessCore")(function* ( } satisfies ProcessRunOutput; }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("ProcessRunner.make")(function* () { const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; diff --git a/apps/server/src/project/AgentSessionScanner.ts b/apps/server/src/project/AgentSessionScanner.ts index 83dc215cca40..32d9232eee8e 100644 --- a/apps/server/src/project/AgentSessionScanner.ts +++ b/apps/server/src/project/AgentSessionScanner.ts @@ -614,6 +614,7 @@ function sameTranscriptIdentity( ); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; // Different project imports can arrive concurrently from multiple clients. diff --git a/apps/server/src/project/ProjectSetupScriptRunner.ts b/apps/server/src/project/ProjectSetupScriptRunner.ts index 6a79c853dc99..00dc8deae9be 100644 --- a/apps/server/src/project/ProjectSetupScriptRunner.ts +++ b/apps/server/src/project/ProjectSetupScriptRunner.ts @@ -83,6 +83,7 @@ export class ProjectSetupScriptRunner extends Context.Service< } >()("t3/project/ProjectSetupScriptRunner") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const projectionSnapshotQuery = yield* ProjectionSnapshotQuery.ProjectionSnapshotQuery; const terminalManager = yield* TerminalManager.TerminalManager; diff --git a/apps/server/src/project/T3ProjectFileLoader.ts b/apps/server/src/project/T3ProjectFileLoader.ts index 00ad9d3835a5..f9dfde2b32dd 100644 --- a/apps/server/src/project/T3ProjectFileLoader.ts +++ b/apps/server/src/project/T3ProjectFileLoader.ts @@ -59,6 +59,7 @@ const logT3ProjectFileLoadError = (error: T3ProjectFileLoadError) => }), ); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; diff --git a/apps/server/src/provider/ClaudeModelCatalog.ts b/apps/server/src/provider/ClaudeModelCatalog.ts index b1fcd6a92bbf..e601e9dc9392 100644 --- a/apps/server/src/provider/ClaudeModelCatalog.ts +++ b/apps/server/src/provider/ClaudeModelCatalog.ts @@ -118,7 +118,7 @@ export function scopeClaudeModelCatalog( return { models: [...builtInModels, ...customCatalogModels] }; } -export function resolveClaudeCatalogModel( +function resolveClaudeCatalogModel( catalog: ClaudeModelCatalog, slugOrAlias: string | null | undefined, ): ClaudeCatalogModel | undefined { @@ -215,7 +215,7 @@ export function isClaudeCatalogUltracodeEffort(effort: string | null | undefined return effort === "ultracode"; } -export function resolveClaudeCatalogContextWindow( +function resolveClaudeCatalogContextWindow( catalog: ClaudeModelCatalog, modelSelection: ModelSelection | undefined, ): string | undefined { diff --git a/apps/server/src/provider/Drivers/ClaudeSkills.ts b/apps/server/src/provider/Drivers/ClaudeSkills.ts index 236fe79f518c..259ceeb4b775 100644 --- a/apps/server/src/provider/Drivers/ClaudeSkills.ts +++ b/apps/server/src/provider/Drivers/ClaudeSkills.ts @@ -104,7 +104,7 @@ function parseSkillFrontmatter(contents: string): SkillFrontmatter { * user and project one. Absent on almost every machine, which is why a missing * file is the normal case rather than an error. */ -export function claudeManagedSettingsPath( +function claudeManagedSettingsPath( path: Path.Path, platform: NodeJS.Platform, environment: NodeJS.ProcessEnv, diff --git a/apps/server/src/provider/Layers/ProviderAdapterRegistry.ts b/apps/server/src/provider/Layers/ProviderAdapterRegistry.ts index 919a345aa988..9e8e3c5d1f90 100644 --- a/apps/server/src/provider/Layers/ProviderAdapterRegistry.ts +++ b/apps/server/src/provider/Layers/ProviderAdapterRegistry.ts @@ -80,13 +80,6 @@ export const ProviderAdapterRegistryLive = Layer.effect( makeProviderAdapterRegistry(), ); -// Exposed for tests that want to build a facade over a pre-assembled -// `ProviderInstanceRegistry` without pulling in the whole boot graph. -export { makeProviderAdapterRegistry }; - -// Re-export for consumers that need the accessor shape. The service tag -// itself lives in `Services/ProviderAdapterRegistry.ts`. -export { ProviderAdapterRegistry } from "../Services/ProviderAdapterRegistry.ts"; // Re-export for consumers (including tests) that construct a // `ProviderInstanceId` before calling `getByInstance`. export { ProviderInstanceId }; diff --git a/apps/server/src/provider/Layers/ProviderEventLoggers.ts b/apps/server/src/provider/Layers/ProviderEventLoggers.ts index a4f0b01e8193..c7188c545573 100644 --- a/apps/server/src/provider/Layers/ProviderEventLoggers.ts +++ b/apps/server/src/provider/Layers/ProviderEventLoggers.ts @@ -61,6 +61,7 @@ export const NoOpProviderEventLoggers: ProviderEventLoggers["Service"] = { /** * Builds both stream views over one shared store. Setup failures are logged * and downgraded to the no-op service so diagnostics never block startup. + * @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const { providerEventLogPath } = yield* ServerConfig; diff --git a/apps/server/src/provider/Layers/ProviderInstanceRegistryLive.ts b/apps/server/src/provider/Layers/ProviderInstanceRegistryLive.ts index 0cc4b6c93cb8..67ccbd167c30 100644 --- a/apps/server/src/provider/Layers/ProviderInstanceRegistryLive.ts +++ b/apps/server/src/provider/Layers/ProviderInstanceRegistryLive.ts @@ -33,7 +33,6 @@ * @module provider/Layers/ProviderInstanceRegistryLive */ import { - defaultInstanceIdForDriver, providerInstanceConfigEnabledFlag, ProviderInstanceId, type ProviderInstanceConfig, @@ -430,5 +429,3 @@ export const ProviderInstanceRegistryMutableLayer = (input: { ), ), ) as Layer.Layer; - -export { defaultInstanceIdForDriver }; diff --git a/apps/server/src/provider/Layers/codexLaunchArgs.ts b/apps/server/src/provider/Layers/codexLaunchArgs.ts index 771a4f0b6ed6..f64ff263e0e3 100644 --- a/apps/server/src/provider/Layers/codexLaunchArgs.ts +++ b/apps/server/src/provider/Layers/codexLaunchArgs.ts @@ -1,14 +1,13 @@ import { tokenizeCliArgs } from "@t3tools/shared/cliArgs"; -export const T3CODE_CODEX_LAUNCH_ARGS_ENV = "T3CODE_CODEX_LAUNCH_ARGS"; +const T3CODE_CODEX_LAUNCH_ARGS_ENV = "T3CODE_CODEX_LAUNCH_ARGS"; export const resolveCodexLaunchArgs = ( launchArgs?: string, environment: NodeJS.ProcessEnv = process.env, ) => environment[T3CODE_CODEX_LAUNCH_ARGS_ENV]?.trim() || launchArgs?.trim() || ""; -export const codexLaunchArgv = (launchArgs?: string): ReadonlyArray => - tokenizeCliArgs(launchArgs); +const codexLaunchArgv = (launchArgs?: string): ReadonlyArray => tokenizeCliArgs(launchArgs); export const codexAppServerArgs = (launchArgs?: string) => [ "app-server", diff --git a/apps/server/src/provider/Layers/codexResetCredit.ts b/apps/server/src/provider/Layers/codexResetCredit.ts index d8310c7c3ee7..62c1a77f26ce 100644 --- a/apps/server/src/provider/Layers/codexResetCredit.ts +++ b/apps/server/src/provider/Layers/codexResetCredit.ts @@ -45,6 +45,7 @@ export class CodexResetCreditCoordinator extends Context.Service< } >()("t3/provider/Layers/codexResetCredit/CodexResetCreditCoordinator") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const crypto = yield* Crypto.Crypto; const statesRef = yield* Ref.make>(new Map()); diff --git a/apps/server/src/provider/Layers/codexUsageLimits.ts b/apps/server/src/provider/Layers/codexUsageLimits.ts index 32862cdb337d..484e50c62b07 100644 --- a/apps/server/src/provider/Layers/codexUsageLimits.ts +++ b/apps/server/src/provider/Layers/codexUsageLimits.ts @@ -66,7 +66,7 @@ function labelForKind(kind: ServerProviderUsageWindow["kind"]): string { * `windowDurationMins`; when it does not, paid plans expose the 5-hour and * weekly pair and Free/Go expose one monthly allowance. */ -export function codexRateLimitsToWindows( +function codexRateLimitsToWindows( snapshot: CodexRateLimitSnapshot, ): ReadonlyArray { // Show the main allowance only. Model-specific notifications (such as Spark) diff --git a/apps/server/src/provider/ModelManifest.ts b/apps/server/src/provider/ModelManifest.ts index 67a7334f613d..65e96f0f6e3d 100644 --- a/apps/server/src/provider/ModelManifest.ts +++ b/apps/server/src/provider/ModelManifest.ts @@ -207,7 +207,7 @@ export const encodeManifestCache = Schema.encodeEffect( ); /** True when the manifest classifies `slug` as legacy for `driverKind`. */ -export function isLegacyModel( +function isLegacyModel( manifest: ModelManifestData, driverKind: ProviderDriverKind, slug: string, @@ -311,7 +311,7 @@ export class ModelManifest extends Context.Service< >()("t3/provider/ModelManifest") {} /** Constant service for tests and callers that only need the bundled data. */ -export const BundledOnlyModelManifest: ModelManifest["Service"] = { +const BundledOnlyModelManifest: ModelManifest["Service"] = { current: Effect.succeed(BUNDLED_MODEL_MANIFEST), refresh: Effect.succeed(BUNDLED_MODEL_MANIFEST), refreshInBackground: Effect.void, diff --git a/apps/server/src/provider/OpenCodeServerOwner.ts b/apps/server/src/provider/OpenCodeServerOwner.ts index cccfcaccd6ef..fe858d3bfc78 100644 --- a/apps/server/src/provider/OpenCodeServerOwner.ts +++ b/apps/server/src/provider/OpenCodeServerOwner.ts @@ -2,13 +2,12 @@ import * as Context from "effect/Context"; import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; import * as Fiber from "effect/Fiber"; -import * as Layer from "effect/Layer"; import * as Scope from "effect/Scope"; import * as Semaphore from "effect/Semaphore"; import * as OpenCodeRuntime from "./opencodeRuntime.ts"; -export const OPENCODE_SERVER_IDLE_TTL = "30 seconds"; +const OPENCODE_SERVER_IDLE_TTL = "30 seconds"; interface OpenCodeServerOwnerState { server: OpenCodeRuntime.OpenCodeServerProcess | null; @@ -175,10 +174,3 @@ export const make = Effect.fn("OpenCodeServerOwner.make")(function* (input: { ), }); }); - -export const layer = (input: { - readonly binaryPath: string; - readonly directory: string; - readonly serverPassword?: string; - readonly environment?: NodeJS.ProcessEnv; -}) => Layer.effect(OpenCodeServerOwner, make(input)); diff --git a/apps/server/src/provider/acp/AntigravityAcpSupport.ts b/apps/server/src/provider/acp/AntigravityAcpSupport.ts index cb37df006587..6e625127cb18 100644 --- a/apps/server/src/provider/acp/AntigravityAcpSupport.ts +++ b/apps/server/src/provider/acp/AntigravityAcpSupport.ts @@ -181,7 +181,7 @@ const AUDIO_MIME_TYPES = new Set([ "audio/x-wav", "audio/webm", ]); -export const ANTIGRAVITY_MAX_AUDIO_ATTACHMENT_BYTES = 20 * 1024 * 1024; +const ANTIGRAVITY_MAX_AUDIO_ATTACHMENT_BYTES = 20 * 1024 * 1024; const TEXT_MIME_TYPES = new Set([ "application/json", "application/ld+json", diff --git a/apps/server/src/provider/acp/AntigravityProtocol.ts b/apps/server/src/provider/acp/AntigravityProtocol.ts index 81ec91d265b0..1993c9457af5 100644 --- a/apps/server/src/provider/acp/AntigravityProtocol.ts +++ b/apps/server/src/provider/acp/AntigravityProtocol.ts @@ -72,9 +72,7 @@ const decodeSecurityWarning = Schema.decodeUnknownOption( * The agent marks "Allow Always" on shell and web tools with a prompt injection * warning in `_meta`. Surface it as option text so both clients can show it. */ -export function antigravitySecurityWarning( - option: EffectAcpSchema.PermissionOption, -): string | undefined { +function antigravitySecurityWarning(option: EffectAcpSchema.PermissionOption): string | undefined { const meta = option._meta; if (!Predicate.isObject(meta)) return undefined; const warning = Option.getOrUndefined(decodeSecurityWarning(meta[SECURITY_WARNING_META_KEY])); diff --git a/apps/server/src/provider/antigravityRelease.ts b/apps/server/src/provider/antigravityRelease.ts index c33f09cef465..90ba309c10c6 100644 --- a/apps/server/src/provider/antigravityRelease.ts +++ b/apps/server/src/provider/antigravityRelease.ts @@ -1,4 +1,4 @@ -export const ANTIGRAVITY_RELEASE_VERSION = "agy_acp_server_1.1.1"; +const ANTIGRAVITY_RELEASE_VERSION = "agy_acp_server_1.1.1"; export interface AntigravityReleaseAsset { readonly version: string; diff --git a/apps/server/src/provider/opencodeRuntime.ts b/apps/server/src/provider/opencodeRuntime.ts index ce2840f6c13d..6d7187792a99 100644 --- a/apps/server/src/provider/opencodeRuntime.ts +++ b/apps/server/src/provider/opencodeRuntime.ts @@ -438,9 +438,9 @@ export function openCodeQuestionId( * puts in the prompt. */ const OPENCODE_NATIVE_IMAGE_MIMES = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]); -export const OPENCODE_NATIVE_FILE_PART_MAX_BYTES = 20 * 1024 * 1024; +const OPENCODE_NATIVE_FILE_PART_MAX_BYTES = 20 * 1024 * 1024; -export function isOpenCodeNativeFilePart(input: { +function isOpenCodeNativeFilePart(input: { readonly mimeType: string; readonly sizeBytes: number; }): boolean { diff --git a/apps/server/src/provider/providerMaintenance.ts b/apps/server/src/provider/providerMaintenance.ts index e8ff090a4ec9..74167a808840 100644 --- a/apps/server/src/provider/providerMaintenance.ts +++ b/apps/server/src/provider/providerMaintenance.ts @@ -33,7 +33,7 @@ const PROVIDER_UPDATE_ACTION_TOAST_MESSAGE = "Install the update now or review p * move on their own, so this mostly bounds how stale a Homebrew "latest" can * get; the npm registry check keeps its own cache. */ -export const MAINTENANCE_CAPABILITIES_CACHE_TTL = Duration.hours(1); +const MAINTENANCE_CAPABILITIES_CACHE_TTL = Duration.hours(1); const compactEnv = (input: Record>): NodeJS.ProcessEnv => Object.fromEntries( diff --git a/apps/server/src/provider/providerMaintenanceRunner.ts b/apps/server/src/provider/providerMaintenanceRunner.ts index e91560312566..8a4ec601410f 100644 --- a/apps/server/src/provider/providerMaintenanceRunner.ts +++ b/apps/server/src/provider/providerMaintenanceRunner.ts @@ -211,6 +211,7 @@ function makeUpdateState(input: { }; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () { const providerRegistry = yield* ProviderRegistry; const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; diff --git a/apps/server/src/provider/providerSnapshot.ts b/apps/server/src/provider/providerSnapshot.ts index 9663aeacb63f..bf09c9950744 100644 --- a/apps/server/src/provider/providerSnapshot.ts +++ b/apps/server/src/provider/providerSnapshot.ts @@ -105,42 +105,6 @@ export const spawnAndCollect = (binaryPath: string, command: ChildProcess.Comman return result; }).pipe(Effect.scoped); -export function detailFromResult( - result: CommandResult & { readonly timedOut?: boolean }, -): string | undefined { - if (result.timedOut) return "Timed out while running command."; - const stderr = nonEmptyTrimmed(result.stderr); - if (stderr) return stderr; - const stdout = nonEmptyTrimmed(result.stdout); - if (stdout) return stdout; - if (result.code !== 0) { - return `Command exited with code ${result.code}.`; - } - return undefined; -} - -export function extractAuthBoolean(value: unknown): boolean | undefined { - if (globalThis.Array.isArray(value)) { - for (const entry of value) { - const nested = extractAuthBoolean(entry); - if (nested !== undefined) return nested; - } - return undefined; - } - - if (!value || typeof value !== "object") return undefined; - - const record = value as Record; - for (const key of ["authenticated", "isAuthenticated", "loggedIn", "isLoggedIn"] as const) { - if (typeof record[key] === "boolean") return record[key]; - } - for (const key of ["auth", "status", "session", "account"] as const) { - const nested = extractAuthBoolean(record[key]); - if (nested !== undefined) return nested; - } - return undefined; -} - export function parseGenericCliVersion(output: string): string | null { const match = output.match(/\b(\d+\.\d+\.\d+)\b/); return match?.[1] ?? null; diff --git a/apps/server/src/provider/providerUpdateSettings.ts b/apps/server/src/provider/providerUpdateSettings.ts index 308d84a14467..30ad2bf8a286 100644 --- a/apps/server/src/provider/providerUpdateSettings.ts +++ b/apps/server/src/provider/providerUpdateSettings.ts @@ -10,7 +10,7 @@ export interface ProviderSnapshotSettings { readonly enableProviderUpdateChecks: boolean; } -export function makeProviderSnapshotSettings( +function makeProviderSnapshotSettings( provider: Settings, settings: ServerSettings, ): ProviderSnapshotSettings { diff --git a/apps/server/src/provider/testUtils/providerRegistryMock.ts b/apps/server/src/provider/testUtils/providerRegistryMock.ts index d9a04de6f607..b2195b1d890c 100644 --- a/apps/server/src/provider/testUtils/providerRegistryMock.ts +++ b/apps/server/src/provider/testUtils/providerRegistryMock.ts @@ -5,7 +5,7 @@ import * as Layer from "effect/Layer"; import * as Stream from "effect/Stream"; import { makeManualOnlyProviderMaintenanceCapabilities } from "../providerMaintenance.ts"; -export const makeProviderRegistryMock = ( +const makeProviderRegistryMock = ( providers: ReadonlyArray = [], ): ProviderRegistryShape => ({ getProviders: Effect.succeed(providers), diff --git a/apps/server/src/pullRequest/AzureDevOpsPullRequestCli.ts b/apps/server/src/pullRequest/AzureDevOpsPullRequestCli.ts index fe87692e1cc3..da9d33756ecc 100644 --- a/apps/server/src/pullRequest/AzureDevOpsPullRequestCli.ts +++ b/apps/server/src/pullRequest/AzureDevOpsPullRequestCli.ts @@ -261,6 +261,7 @@ function isReviewerName(value: string): boolean { return name.length > 0 && !name.startsWith("-"); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const azure = yield* AzureDevOpsCli.AzureDevOpsCli; diff --git a/apps/server/src/pullRequest/BitbucketPullRequestApi.ts b/apps/server/src/pullRequest/BitbucketPullRequestApi.ts index 5b3149b0d75c..91b74067f8fb 100644 --- a/apps/server/src/pullRequest/BitbucketPullRequestApi.ts +++ b/apps/server/src/pullRequest/BitbucketPullRequestApi.ts @@ -378,6 +378,7 @@ function bitbucketReviewPosition( } } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const bitbucket = yield* BitbucketApi.BitbucketApi; diff --git a/apps/server/src/pullRequest/GitHubPullRequestCli.ts b/apps/server/src/pullRequest/GitHubPullRequestCli.ts index 89a50f93ced7..127561b218d8 100644 --- a/apps/server/src/pullRequest/GitHubPullRequestCli.ts +++ b/apps/server/src/pullRequest/GitHubPullRequestCli.ts @@ -714,7 +714,7 @@ export class GitHubPullRequestCli extends Context.Service< * The host is not read off the identity: it travels alongside it, because the identity a * project records is the path below its host and never names the host itself. */ -export function parseRepositorySelector(value: string): { +function parseRepositorySelector(value: string): { readonly owner: string; readonly name: string; } { @@ -980,6 +980,7 @@ function actionArgs( } } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const github = yield* GitHubCli.GitHubCli; const graphQlBudget = yield* GitHubGraphQlBudget.GitHubGraphQlBudget; diff --git a/apps/server/src/pullRequest/GitLabPullRequestCli.ts b/apps/server/src/pullRequest/GitLabPullRequestCli.ts index f291cbd89c7f..b4d6607a6fb5 100644 --- a/apps/server/src/pullRequest/GitLabPullRequestCli.ts +++ b/apps/server/src/pullRequest/GitLabPullRequestCli.ts @@ -511,6 +511,7 @@ function actionArgs( } } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const gitlab = yield* GitLabCli.GitLabCli; diff --git a/apps/server/src/pullRequest/PullRequestProviderRegistry.ts b/apps/server/src/pullRequest/PullRequestProviderRegistry.ts index d2caf3ff35bd..f6b97383ef81 100644 --- a/apps/server/src/pullRequest/PullRequestProviderRegistry.ts +++ b/apps/server/src/pullRequest/PullRequestProviderRegistry.ts @@ -41,6 +41,7 @@ export function fromProviders( /** * The hosts this build can read change requests from. A host with no entry here still shows up * in the provider list as unimplemented, so its projects are explained rather than missing. + * @public Service construction is part of the module API alongside layer. */ export const make = Effect.map( Effect.all([ diff --git a/apps/server/src/relay/AgentAwarenessRelay.ts b/apps/server/src/relay/AgentAwarenessRelay.ts index 8d7b9e98361e..538e7033af30 100644 --- a/apps/server/src/relay/AgentAwarenessRelay.ts +++ b/apps/server/src/relay/AgentAwarenessRelay.ts @@ -211,7 +211,7 @@ const makePublishProof = Effect.fn("makePublishProof")(function* (input: { }); // Compact, log-safe view of the fields the awareness phase ladder reads. -export function describeThreadShellForAwareness( +function describeThreadShellForAwareness( thread: Option.Option, ): Record { if (Option.isNone(thread)) { @@ -290,6 +290,7 @@ export function resolveAgentAwarenessRelayActiveThreadIds(input: { .map((thread) => thread.id); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const secrets = yield* ServerSecretStore.ServerSecretStore; const serverEnvironment = yield* ServerEnvironment.ServerEnvironment; diff --git a/apps/server/src/resourceTelemetry/DesktopTelemetryReceiver.ts b/apps/server/src/resourceTelemetry/DesktopTelemetryReceiver.ts index 1297b3bdf765..9a9d02dcdbbe 100644 --- a/apps/server/src/resourceTelemetry/DesktopTelemetryReceiver.ts +++ b/apps/server/src/resourceTelemetry/DesktopTelemetryReceiver.ts @@ -327,6 +327,7 @@ export function requireDesktopTelemetryWriteProgress( : Effect.fail(new DesktopTelemetryControlStalled({ fd, remainingBytes })); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(function* () { const config = yield* ServerConfig; const serverSettings = yield* ServerSettingsService; diff --git a/apps/server/src/resourceTelemetry/Model.ts b/apps/server/src/resourceTelemetry/Model.ts index a198c4b311f7..2582d7e9c17f 100644 --- a/apps/server/src/resourceTelemetry/Model.ts +++ b/apps/server/src/resourceTelemetry/Model.ts @@ -68,7 +68,7 @@ export interface MergeProcessesResult { readonly deltas: ReadonlyArray; } -export const emptyGroupCounters = (): GroupCounters => ({ +const emptyGroupCounters = (): GroupCounters => ({ cpuTimeMs: 0, ioReadBytes: 0, ioWriteBytes: 0, diff --git a/apps/server/src/resourceTelemetry/NativeTelemetryClient.ts b/apps/server/src/resourceTelemetry/NativeTelemetryClient.ts index 9ddc72d61ebd..35f701050f0d 100644 --- a/apps/server/src/resourceTelemetry/NativeTelemetryClient.ts +++ b/apps/server/src/resourceTelemetry/NativeTelemetryClient.ts @@ -360,6 +360,7 @@ export function canCommandNativeTelemetrySidecar( return hasHandle && (status === "healthy" || status === "degraded"); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(function* () { const binary = yield* ResourceMonitorBinary.ResourceMonitorBinary; const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; diff --git a/apps/server/src/resourceTelemetry/ResourceMonitorBinary.ts b/apps/server/src/resourceTelemetry/ResourceMonitorBinary.ts index c93bc54a1fba..650f0ffbccd1 100644 --- a/apps/server/src/resourceTelemetry/ResourceMonitorBinary.ts +++ b/apps/server/src/resourceTelemetry/ResourceMonitorBinary.ts @@ -90,7 +90,7 @@ export const ResourceMonitorHostLinuxLibc = Context.Reference()("t3/review/ReviewService") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const config = yield* ServerConfig.ServerConfig; const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/server/src/server.ts b/apps/server/src/server.ts index 349644966f26..fd8ee4a4f699 100644 --- a/apps/server/src/server.ts +++ b/apps/server/src/server.ts @@ -564,7 +564,7 @@ export const makeRoutesLayer = Layer.mergeAll( Layer.provide(httpCompressionLayer), ); -export const makeServerLayer = Layer.unwrap( +const makeServerLayer = Layer.unwrap( Effect.gen(function* () { const config = yield* ServerConfig.ServerConfig; const activation = yield* Deferred.make(); diff --git a/apps/server/src/serverRuntimeStartup.ts b/apps/server/src/serverRuntimeStartup.ts index 0905439257ff..36074865bcf7 100644 --- a/apps/server/src/serverRuntimeStartup.ts +++ b/apps/server/src/serverRuntimeStartup.ts @@ -147,7 +147,7 @@ export const makeCommandGate = Effect.gen(function* () { } satisfies CommandGate; }); -export const recordStartupHeartbeat = Effect.gen(function* () { +const recordStartupHeartbeat = Effect.gen(function* () { const analytics = yield* AnalyticsService.AnalyticsService; const projectionSnapshotQuery = yield* ProjectionSnapshotQuery.ProjectionSnapshotQuery; @@ -466,7 +466,7 @@ const clearContinuationMarkers = ( { concurrency: "unbounded", discard: true }, ); -export const clearProviderSessionContinuationMarkers = (threadIds: ReadonlyArray) => +const clearProviderSessionContinuationMarkers = (threadIds: ReadonlyArray) => Effect.gen(function* () { const directory = yield* ProviderSessionDirectory.ProviderSessionDirectory; yield* clearContinuationMarkers(directory, threadIds); @@ -803,6 +803,7 @@ export const autoPullProjects = Effect.fn("autoPullProjects")(function* ( ); }); +/** @public Service construction is part of the module API alongside layer. */ export const make = (options?: StartupOptions) => Effect.gen(function* () { const serverConfig = yield* ServerConfig.ServerConfig; diff --git a/apps/server/src/serverSettings.ts b/apps/server/src/serverSettings.ts index fe72147dfa0c..0b64d445adf8 100644 --- a/apps/server/src/serverSettings.ts +++ b/apps/server/src/serverSettings.ts @@ -142,7 +142,7 @@ function providerEnvironmentSecretName(input: { */ const USAGE_LIMIT_SOURCE_KEY_REDACTED = "\u2022\u2022\u2022\u2022\u2022\u2022"; -export function usageLimitSourceSecretName(sourceId: string): string { +function usageLimitSourceSecretName(sourceId: string): string { return `usage-limit-source-${Buffer.from(sourceId, "utf8").toString("base64url")}`; } diff --git a/apps/server/src/sourceControl/AzureDevOpsCli.ts b/apps/server/src/sourceControl/AzureDevOpsCli.ts index f05f4a7588c4..28a7d4b10d30 100644 --- a/apps/server/src/sourceControl/AzureDevOpsCli.ts +++ b/apps/server/src/sourceControl/AzureDevOpsCli.ts @@ -203,8 +203,6 @@ export const AzureDevOpsCliError = Schema.Union([ ]); export type AzureDevOpsCliError = typeof AzureDevOpsCliError.Type; -export const isAzureDevOpsCliError = Schema.is(AzureDevOpsCliError); - export interface AzureDevOpsRepositoryCloneUrls { readonly nameWithOwner: string; readonly url: string; @@ -352,6 +350,7 @@ function decodeAzureDevOpsJson( ); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const process = yield* VcsProcess.VcsProcess; diff --git a/apps/server/src/sourceControl/AzureDevOpsSourceControlProvider.ts b/apps/server/src/sourceControl/AzureDevOpsSourceControlProvider.ts index 20a74cc8a5d7..c2f6a5efc65a 100644 --- a/apps/server/src/sourceControl/AzureDevOpsSourceControlProvider.ts +++ b/apps/server/src/sourceControl/AzureDevOpsSourceControlProvider.ts @@ -1,5 +1,4 @@ import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; import { SourceControlProviderError, type ChangeRequest } from "@t3tools/contracts"; import * as AzureDevOpsCli from "./AzureDevOpsCli.ts"; @@ -235,5 +234,3 @@ export const make = Effect.gen(function* () { ), }); }); - -export const layer = Layer.effect(SourceControlProvider.SourceControlProvider, make); diff --git a/apps/server/src/sourceControl/BitbucketApi.ts b/apps/server/src/sourceControl/BitbucketApi.ts index 4573f2891f85..711afe265e0d 100644 --- a/apps/server/src/sourceControl/BitbucketApi.ts +++ b/apps/server/src/sourceControl/BitbucketApi.ts @@ -262,7 +262,7 @@ export const BitbucketApiError = Schema.Union([ BitbucketCheckoutError, ]); export type BitbucketApiError = typeof BitbucketApiError.Type; -export const isBitbucketApiError = Schema.is(BitbucketApiError); +const isBitbucketApiError = Schema.is(BitbucketApiError); const RawBitbucketRepositorySchema = Schema.Struct({ full_name: TrimmedNonEmptyString, @@ -606,6 +606,7 @@ function responseError( }); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const config = yield* BitbucketApiEnvConfig; const httpClient = yield* HttpClient.HttpClient; diff --git a/apps/server/src/sourceControl/BitbucketSourceControlProvider.ts b/apps/server/src/sourceControl/BitbucketSourceControlProvider.ts index ffa3fb1301c9..e27aa4c7dc88 100644 --- a/apps/server/src/sourceControl/BitbucketSourceControlProvider.ts +++ b/apps/server/src/sourceControl/BitbucketSourceControlProvider.ts @@ -1,5 +1,4 @@ import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import { SourceControlProviderError, type ChangeRequest } from "@t3tools/contracts"; @@ -186,8 +185,6 @@ export const make = Effect.gen(function* () { }); }); -export const layer = Layer.effect(SourceControlProvider.SourceControlProvider, make); - export const makeDiscovery = Effect.gen(function* () { const bitbucket = yield* BitbucketApi.BitbucketApi; diff --git a/apps/server/src/sourceControl/GitHubCli.ts b/apps/server/src/sourceControl/GitHubCli.ts index 85736a95c5dd..dccc0640b860 100644 --- a/apps/server/src/sourceControl/GitHubCli.ts +++ b/apps/server/src/sourceControl/GitHubCli.ts @@ -338,6 +338,7 @@ function deriveRepositoryCloneUrlsFromCreateOutput( }; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const process = yield* VcsProcess.VcsProcess; diff --git a/apps/server/src/sourceControl/GitHubSourceControlProvider.ts b/apps/server/src/sourceControl/GitHubSourceControlProvider.ts index 74f08a9a9127..d82832564a24 100644 --- a/apps/server/src/sourceControl/GitHubSourceControlProvider.ts +++ b/apps/server/src/sourceControl/GitHubSourceControlProvider.ts @@ -1,6 +1,5 @@ import * as DateTime from "effect/DateTime"; import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as Result from "effect/Result"; import { @@ -322,5 +321,3 @@ export const make = Effect.gen(function* () { ), }); }); - -export const layer = Layer.effect(SourceControlProvider.SourceControlProvider, make); diff --git a/apps/server/src/sourceControl/GitLabCli.ts b/apps/server/src/sourceControl/GitLabCli.ts index 9f76a6182ce4..dc299a459099 100644 --- a/apps/server/src/sourceControl/GitLabCli.ts +++ b/apps/server/src/sourceControl/GitLabCli.ts @@ -237,7 +237,6 @@ export const GitLabCliError = Schema.Union([ GitLabNamespaceDecodeError, ]); export type GitLabCliError = typeof GitLabCliError.Type; -export const isGitLabCliError = Schema.is(GitLabCliError); export interface GitLabMergeRequestSummary { readonly number: number; @@ -409,6 +408,7 @@ function parseRepositoryPath(repository: string): { return { namespacePath, projectPath }; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const process = yield* VcsProcess.VcsProcess; diff --git a/apps/server/src/sourceControl/GitLabSourceControlProvider.ts b/apps/server/src/sourceControl/GitLabSourceControlProvider.ts index 28211c6b8509..5eb9b326423f 100644 --- a/apps/server/src/sourceControl/GitLabSourceControlProvider.ts +++ b/apps/server/src/sourceControl/GitLabSourceControlProvider.ts @@ -1,5 +1,4 @@ import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import { SourceControlProviderError, type ChangeRequest } from "@t3tools/contracts"; @@ -250,5 +249,3 @@ export const make = Effect.gen(function* () { ), }); }); - -export const layer = Layer.effect(SourceControlProvider.SourceControlProvider, make); diff --git a/apps/server/src/sourceControl/SourceControlDiscovery.ts b/apps/server/src/sourceControl/SourceControlDiscovery.ts index 660f32283e0f..eee0e19f0049 100644 --- a/apps/server/src/sourceControl/SourceControlDiscovery.ts +++ b/apps/server/src/sourceControl/SourceControlDiscovery.ts @@ -64,6 +64,7 @@ export class SourceControlDiscovery extends Context.Service< } >()("t3/sourceControl/SourceControlDiscovery") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const config = yield* ServerConfig; const process = yield* VcsProcess.VcsProcess; diff --git a/apps/server/src/sourceControl/SourceControlProvider.ts b/apps/server/src/sourceControl/SourceControlProvider.ts index 5f93dbcaa425..1844e1bfa7cb 100644 --- a/apps/server/src/sourceControl/SourceControlProvider.ts +++ b/apps/server/src/sourceControl/SourceControlProvider.ts @@ -61,7 +61,7 @@ export function parseSourceControlOwnerRef( return owner && refName ? { owner, refName } : undefined; } -export function normalizeSourceBranch(headSelector: string): string { +function normalizeSourceBranch(headSelector: string): string { return parseSourceControlOwnerRef(headSelector)?.refName ?? headSelector.trim(); } diff --git a/apps/server/src/sourceControl/SourceControlProviderDiscovery.ts b/apps/server/src/sourceControl/SourceControlProviderDiscovery.ts index b2b9e4513378..69ac90edbfb3 100644 --- a/apps/server/src/sourceControl/SourceControlProviderDiscovery.ts +++ b/apps/server/src/sourceControl/SourceControlProviderDiscovery.ts @@ -115,7 +115,7 @@ export function providerAuth(input: { }; } -export function unknownAuth(detail?: string): SourceControlProviderAuth { +function unknownAuth(detail?: string): SourceControlProviderAuth { return providerAuth({ status: "unknown", detail }); } diff --git a/apps/server/src/sourceControl/SourceControlProviderRegistry.ts b/apps/server/src/sourceControl/SourceControlProviderRegistry.ts index 9fe089a4184c..c544350782e3 100644 --- a/apps/server/src/sourceControl/SourceControlProviderRegistry.ts +++ b/apps/server/src/sourceControl/SourceControlProviderRegistry.ts @@ -194,103 +194,103 @@ function bindProviderContext( }); } -export const makeWithProviders = Effect.fn("makeSourceControlProviderRegistryWithProviders")( - function* (registrations: ReadonlyArray) { - const config = yield* ServerConfig; - const process = yield* VcsProcess.VcsProcess; - const vcsRegistry = yield* VcsDriverRegistry.VcsDriverRegistry; - const providers = new Map< - SourceControlProviderKind, - SourceControlProvider.SourceControlProvider["Service"] - >(registrations.map((registration) => [registration.kind, registration.provider])); - const discoverySpecs = registrations.map((registration) => registration.discovery); +const makeWithProviders = Effect.fn("makeSourceControlProviderRegistryWithProviders")(function* ( + registrations: ReadonlyArray, +) { + const config = yield* ServerConfig; + const process = yield* VcsProcess.VcsProcess; + const vcsRegistry = yield* VcsDriverRegistry.VcsDriverRegistry; + const providers = new Map< + SourceControlProviderKind, + SourceControlProvider.SourceControlProvider["Service"] + >(registrations.map((registration) => [registration.kind, registration.provider])); + const discoverySpecs = registrations.map((registration) => registration.discovery); - const get: SourceControlProviderRegistry["Service"]["get"] = (kind) => - Effect.succeed(providers.get(kind) ?? unsupportedProvider(kind)); + const get: SourceControlProviderRegistry["Service"]["get"] = (kind) => + Effect.succeed(providers.get(kind) ?? unsupportedProvider(kind)); - const detectProviderContext = Effect.fn("SourceControlProviderRegistry.detectProviderContext")( - function* (cwd: string) { - const handle = yield* vcsRegistry.resolve({ cwd }).pipe( - Effect.mapError( - (error) => - new SourceControlProviderError({ - provider: "unknown", - operation: "detectProvider", - cwd, - detail: "Failed to detect source control provider.", - cause: error, - }), - ), - ); - const remotes = yield* handle.driver.listRemotes(cwd).pipe( - Effect.mapError( - (error) => - new SourceControlProviderError({ - provider: "unknown", - operation: "detectProvider", - cwd, - detail: "Failed to detect source control provider.", - cause: error, - }), - ), - ); - const context = selectProviderContext(remotes.remotes); + const detectProviderContext = Effect.fn("SourceControlProviderRegistry.detectProviderContext")( + function* (cwd: string) { + const handle = yield* vcsRegistry.resolve({ cwd }).pipe( + Effect.mapError( + (error) => + new SourceControlProviderError({ + provider: "unknown", + operation: "detectProvider", + cwd, + detail: "Failed to detect source control provider.", + cause: error, + }), + ), + ); + const remotes = yield* handle.driver.listRemotes(cwd).pipe( + Effect.mapError( + (error) => + new SourceControlProviderError({ + provider: "unknown", + operation: "detectProvider", + cwd, + detail: "Failed to detect source control provider.", + cause: error, + }), + ), + ); + const context = selectProviderContext(remotes.remotes); + + return yield* refineUnknownRemoteProvider({ + specs: discoverySpecs, + process, + cwd, + context, + }); + }, + ); + + const providerContextCache = yield* Cache.makeWith< + string, + SourceControlProvider.SourceControlProviderContext | null, + SourceControlProviderError + >(detectProviderContext, { + capacity: PROVIDER_DETECTION_CACHE_CAPACITY, + timeToLive: (exit) => (Exit.isSuccess(exit) ? PROVIDER_DETECTION_CACHE_TTL : Duration.zero), + }); - return yield* refineUnknownRemoteProvider({ + const resolveHandle: SourceControlProviderRegistry["Service"]["resolveHandle"] = (input) => + (input.context === undefined + ? Cache.get(providerContextCache, input.cwd) + : refineUnknownRemoteProvider({ specs: discoverySpecs, process, - cwd, + cwd: input.cwd, + context: input.context, + }) + ).pipe( + Effect.map((context) => { + const kind = context?.provider.kind ?? "unknown"; + const provider = providers.get(kind) ?? unsupportedProvider(kind); + return { + provider: bindProviderContext(provider, context), context, - }); - }, + } satisfies SourceControlProviderHandle; + }), ); - const providerContextCache = yield* Cache.makeWith< - string, - SourceControlProvider.SourceControlProviderContext | null, - SourceControlProviderError - >(detectProviderContext, { - capacity: PROVIDER_DETECTION_CACHE_CAPACITY, - timeToLive: (exit) => (Exit.isSuccess(exit) ? PROVIDER_DETECTION_CACHE_TTL : Duration.zero), - }); - - const resolveHandle: SourceControlProviderRegistry["Service"]["resolveHandle"] = (input) => - (input.context === undefined - ? Cache.get(providerContextCache, input.cwd) - : refineUnknownRemoteProvider({ - specs: discoverySpecs, - process, - cwd: input.cwd, - context: input.context, - }) - ).pipe( - Effect.map((context) => { - const kind = context?.provider.kind ?? "unknown"; - const provider = providers.get(kind) ?? unsupportedProvider(kind); - return { - provider: bindProviderContext(provider, context), - context, - } satisfies SourceControlProviderHandle; + return SourceControlProviderRegistry.of({ + get, + resolveHandle, + resolve: (input) => resolveHandle(input).pipe(Effect.map((handle) => handle.provider)), + discover: Effect.all( + discoverySpecs.map((spec) => + probeSourceControlProvider({ + spec, + process, + cwd: config.cwd, }), - ); - - return SourceControlProviderRegistry.of({ - get, - resolveHandle, - resolve: (input) => resolveHandle(input).pipe(Effect.map((handle) => handle.provider)), - discover: Effect.all( - discoverySpecs.map((spec) => - probeSourceControlProvider({ - spec, - process, - cwd: config.cwd, - }), - ), - { concurrency: "unbounded" }, ), - }); - }, -); + { concurrency: "unbounded" }, + ), + }); +}); export const make = Effect.gen(function* () { const github = yield* GitHubSourceControlProvider.make; diff --git a/apps/server/src/sourceControl/SourceControlRateLimit.ts b/apps/server/src/sourceControl/SourceControlRateLimit.ts index e8f7218de3b9..2b4fe1d5441c 100644 --- a/apps/server/src/sourceControl/SourceControlRateLimit.ts +++ b/apps/server/src/sourceControl/SourceControlRateLimit.ts @@ -82,6 +82,7 @@ export function retryAtFromHeader(value: string | undefined, now: number): numbe return Number.isFinite(retryAt) && retryAt > now ? retryAt : undefined; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const entries = yield* Ref.make>(new Map()); diff --git a/apps/server/src/sourceControl/SourceControlRepositoryService.ts b/apps/server/src/sourceControl/SourceControlRepositoryService.ts index b38fe3d5c302..39959e402eea 100644 --- a/apps/server/src/sourceControl/SourceControlRepositoryService.ts +++ b/apps/server/src/sourceControl/SourceControlRepositoryService.ts @@ -77,6 +77,7 @@ function selectRemoteUrl( } } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const config = yield* ServerConfig; const fileSystem = yield* FileSystem.FileSystem; diff --git a/apps/server/src/sourceControl/azureDevOpsPullRequests.ts b/apps/server/src/sourceControl/azureDevOpsPullRequests.ts index 24c0e49fd8f4..d11d1a87077a 100644 --- a/apps/server/src/sourceControl/azureDevOpsPullRequests.ts +++ b/apps/server/src/sourceControl/azureDevOpsPullRequests.ts @@ -5,7 +5,7 @@ import * as Option from "effect/Option"; import * as Result from "effect/Result"; import * as Schema from "effect/Schema"; import { PositiveInt, TrimmedNonEmptyString } from "@t3tools/contracts"; -import { decodeJsonResult, formatSchemaError } from "@t3tools/shared/schemaJson"; +import { decodeJsonResult } from "@t3tools/shared/schemaJson"; export interface NormalizedAzureDevOpsPullRequestRecord { readonly number: number; @@ -190,8 +190,6 @@ const decodeAzureDevOpsPullRequestList = decodeJsonResult(Schema.Array(Schema.Un const decodeAzureDevOpsPullRequest = decodeJsonResult(AzureDevOpsPullRequestSchema); const decodeAzureDevOpsPullRequestEntry = Schema.decodeUnknownExit(AzureDevOpsPullRequestSchema); -export const formatAzureDevOpsJsonDecodeError = formatSchemaError; - export function decodeAzureDevOpsPullRequestListJson( raw: string, ): Result.Result< diff --git a/apps/server/src/sourceControl/gitHubPullRequests.ts b/apps/server/src/sourceControl/gitHubPullRequests.ts index 822de1e02797..b233d900adf1 100644 --- a/apps/server/src/sourceControl/gitHubPullRequests.ts +++ b/apps/server/src/sourceControl/gitHubPullRequests.ts @@ -5,7 +5,7 @@ import * as Option from "effect/Option"; import * as Result from "effect/Result"; import * as Schema from "effect/Schema"; import { PositiveInt, TrimmedNonEmptyString } from "@t3tools/contracts"; -import { decodeJsonResult, formatSchemaError } from "@t3tools/shared/schemaJson"; +import { decodeJsonResult } from "@t3tools/shared/schemaJson"; export interface NormalizedGitHubPullRequestRecord { readonly number: number; @@ -114,8 +114,6 @@ const decodeGitHubPullRequestList = decodeJsonResult(Schema.Array(Schema.Unknown const decodeGitHubPullRequest = decodeJsonResult(GitHubPullRequestSchema); const decodeGitHubPullRequestEntry = Schema.decodeUnknownExit(GitHubPullRequestSchema); -export const formatGitHubJsonDecodeError = formatSchemaError; - export function decodeGitHubPullRequestListJson( raw: string, ): Result.Result< diff --git a/apps/server/src/sourceControl/gitLabMergeRequests.ts b/apps/server/src/sourceControl/gitLabMergeRequests.ts index 0525260df51b..d03d43411224 100644 --- a/apps/server/src/sourceControl/gitLabMergeRequests.ts +++ b/apps/server/src/sourceControl/gitLabMergeRequests.ts @@ -5,7 +5,7 @@ import * as Option from "effect/Option"; import * as Result from "effect/Result"; import * as Schema from "effect/Schema"; import { PositiveInt, TrimmedNonEmptyString } from "@t3tools/contracts"; -import { decodeJsonResult, formatSchemaError } from "@t3tools/shared/schemaJson"; +import { decodeJsonResult } from "@t3tools/shared/schemaJson"; export interface NormalizedGitLabMergeRequestRecord { readonly number: number; @@ -129,8 +129,6 @@ const decodeGitLabMergeRequestList = decodeJsonResult(Schema.Array(Schema.Unknow const decodeGitLabMergeRequest = decodeJsonResult(GitLabMergeRequestSchema); const decodeGitLabMergeRequestEntry = Schema.decodeUnknownExit(GitLabMergeRequestSchema); -export const formatGitLabJsonDecodeError = formatSchemaError; - export function decodeGitLabMergeRequestListJson( raw: string, ): Result.Result< diff --git a/apps/server/src/sourceControl/githubGraphQlBudget.ts b/apps/server/src/sourceControl/githubGraphQlBudget.ts index 9ece27547f5e..032a83767cc0 100644 --- a/apps/server/src/sourceControl/githubGraphQlBudget.ts +++ b/apps/server/src/sourceControl/githubGraphQlBudget.ts @@ -77,6 +77,7 @@ function withRateLimit(document: string): string { return `${document.slice(0, end)}\n ${RATE_LIMIT_SELECTION}\n${document.slice(end)}`; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const snapshots = yield* Ref.make>(new Map()); diff --git a/apps/server/src/telemetry/AnalyticsService.ts b/apps/server/src/telemetry/AnalyticsService.ts index 423ba8d86f7d..1e5e32b978f1 100644 --- a/apps/server/src/telemetry/AnalyticsService.ts +++ b/apps/server/src/telemetry/AnalyticsService.ts @@ -67,7 +67,7 @@ export class AnalyticsService extends Context.Service< ); } -export function serverOsFromNodePlatform(platform: string): ClientOs { +function serverOsFromNodePlatform(platform: string): ClientOs { switch (platform) { case "darwin": return "macOS"; @@ -82,6 +82,7 @@ export function serverOsFromNodePlatform(platform: string): ClientOs { } } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const telemetryConfig = yield* TelemetryEnvConfig; const httpClient = yield* HttpClient.HttpClient; diff --git a/apps/server/src/terminal/Manager.ts b/apps/server/src/terminal/Manager.ts index 10143b7be20b..21f9714070ae 100644 --- a/apps/server/src/terminal/Manager.ts +++ b/apps/server/src/terminal/Manager.ts @@ -1385,6 +1385,7 @@ export const resolveProviderInstanceTerminalEnvironment = Effect.fn( ); }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.fn("TerminalManager.make")(function* () { const { terminalLogsDir } = yield* ServerConfig.ServerConfig; const ptyAdapter = yield* PtyAdapter.PtyAdapter; diff --git a/apps/server/src/textGeneration/TextGeneration.ts b/apps/server/src/textGeneration/TextGeneration.ts index cc9b2e3926f3..8bdbc47f3717 100644 --- a/apps/server/src/textGeneration/TextGeneration.ts +++ b/apps/server/src/textGeneration/TextGeneration.ts @@ -153,6 +153,7 @@ export const makeTextGenerationFromRegistry = ( ), }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const registry = yield* ProviderInstanceRegistry.ProviderInstanceRegistry; return makeTextGenerationFromRegistry(registry); diff --git a/apps/server/src/textGeneration/TextGenerationPresets.ts b/apps/server/src/textGeneration/TextGenerationPresets.ts index 0f5d03480f49..5fab9219080f 100644 --- a/apps/server/src/textGeneration/TextGenerationPresets.ts +++ b/apps/server/src/textGeneration/TextGenerationPresets.ts @@ -1,10 +1,5 @@ import type { TextGenerationPolicy } from "./TextGenerationPolicy.ts"; -export const defaultTextGenerationPolicy: TextGenerationPolicy = { - kind: "default", - inferRepositoryConventions: false, -}; - export const conventionalCommitsTextGenerationPolicy: TextGenerationPolicy = { kind: "conventional_commits", commitInstructions: diff --git a/apps/server/src/usage/UsageLimitSources.ts b/apps/server/src/usage/UsageLimitSources.ts index a63651f93c21..f992c2c61740 100644 --- a/apps/server/src/usage/UsageLimitSources.ts +++ b/apps/server/src/usage/UsageLimitSources.ts @@ -60,6 +60,7 @@ function sourceLabel(id: string, config: UsageLimitSourceConfig): string { } } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const api = yield* makeCliproxyApi; const settingsService = yield* ServerSettingsService; diff --git a/apps/server/src/usage/usageAggregation.ts b/apps/server/src/usage/usageAggregation.ts index 01a1195efb60..2ad3893ad4e6 100644 --- a/apps/server/src/usage/usageAggregation.ts +++ b/apps/server/src/usage/usageAggregation.ts @@ -23,7 +23,7 @@ import { cacheSavingsUsd, priceUsage, type RateTable } from "./usagePricing.ts"; * `en-CA` yields ISO-ordered parts, which is why it is used here rather than * assembling the day from `Date` getters (those are host-local only). */ -export function makeDayFormatter(timeZone: string): (timestampMs: number) => string { +function makeDayFormatter(timeZone: string): (timestampMs: number) => string { let format: Intl.DateTimeFormat; try { format = new Intl.DateTimeFormat("en-CA", { diff --git a/apps/server/src/usage/usageScanCache.ts b/apps/server/src/usage/usageScanCache.ts index 102058a07d35..224f109147e4 100644 --- a/apps/server/src/usage/usageScanCache.ts +++ b/apps/server/src/usage/usageScanCache.ts @@ -26,7 +26,7 @@ import type { CodexScanState, UsageRecord } from "./usageTranscripts.ts"; // entries would keep serving double-counted records forever. // v3: entries carry the parse position and reducer state so a grown file // re-parses only its appended bytes instead of starting over. -export const USAGE_SCAN_CACHE_VERSION = 3 as const; +const USAGE_SCAN_CACHE_VERSION = 3 as const; export interface CachedFile { readonly size: number; diff --git a/apps/server/src/usage/usageTranscripts.ts b/apps/server/src/usage/usageTranscripts.ts index 2aea60709666..5d909379eb10 100644 --- a/apps/server/src/usage/usageTranscripts.ts +++ b/apps/server/src/usage/usageTranscripts.ts @@ -79,7 +79,7 @@ export function mightCarryUsage(line: string, provider: UsageProviderKind): bool */ export const GROK_COST_USD_TICKS_PER_DOLLAR = 10_000_000_000; -export function grokCostTicksToUsd(ticks: unknown): number | null { +function grokCostTicksToUsd(ticks: unknown): number | null { if (typeof ticks !== "number" || !Number.isFinite(ticks) || ticks < 0) return null; return ticks / GROK_COST_USD_TICKS_PER_DOLLAR; } diff --git a/apps/server/src/vcs/VcsProjectConfig.ts b/apps/server/src/vcs/VcsProjectConfig.ts index 6abce9a3ef31..c14e4fb8e77a 100644 --- a/apps/server/src/vcs/VcsProjectConfig.ts +++ b/apps/server/src/vcs/VcsProjectConfig.ts @@ -64,6 +64,7 @@ const logVcsProjectConfigError = (error: VcsProjectConfigError) => }), ); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; diff --git a/apps/server/src/vcs/VcsProvisioningService.ts b/apps/server/src/vcs/VcsProvisioningService.ts index 9febacf2256a..c0bbb1e6bea2 100644 --- a/apps/server/src/vcs/VcsProvisioningService.ts +++ b/apps/server/src/vcs/VcsProvisioningService.ts @@ -35,6 +35,7 @@ function resolveRequestedKind( return Effect.succeed(kind); } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const registry = yield* VcsDriverRegistry.VcsDriverRegistry; diff --git a/apps/server/src/vcs/VcsStatusBroadcaster.ts b/apps/server/src/vcs/VcsStatusBroadcaster.ts index c00a07f2a7a9..77cf61b86508 100644 --- a/apps/server/src/vcs/VcsStatusBroadcaster.ts +++ b/apps/server/src/vcs/VcsStatusBroadcaster.ts @@ -217,6 +217,7 @@ const normalizeCwd = (cwd: string) => Effect.orElseSucceed(() => cwd), ); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const autoPullPolicy = yield* VcsAutoPullPolicy; const workflow = yield* GitWorkflowService.GitWorkflowService; diff --git a/apps/server/src/workspace/WorkspaceEntries.ts b/apps/server/src/workspace/WorkspaceEntries.ts index 2cf45a1a9cd8..ad5e36e6d8b0 100644 --- a/apps/server/src/workspace/WorkspaceEntries.ts +++ b/apps/server/src/workspace/WorkspaceEntries.ts @@ -128,6 +128,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu return path.resolve(expandHomePathWith(input.cwd, path), input.partialPath); }); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const path = yield* Path.Path; const workspacePaths = yield* WorkspacePaths.WorkspacePaths; diff --git a/apps/server/src/workspace/WorkspaceFileSystem.ts b/apps/server/src/workspace/WorkspaceFileSystem.ts index 055ab51feaeb..4032d2cba974 100644 --- a/apps/server/src/workspace/WorkspaceFileSystem.ts +++ b/apps/server/src/workspace/WorkspaceFileSystem.ts @@ -132,6 +132,7 @@ export class WorkspaceFileSystem extends Context.Service< } >()("t3/workspace/WorkspaceFileSystem") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; diff --git a/apps/server/src/workspace/WorkspaceSearchIndex.ts b/apps/server/src/workspace/WorkspaceSearchIndex.ts index eeb2df342c2c..f7601a44e4c6 100644 --- a/apps/server/src/workspace/WorkspaceSearchIndex.ts +++ b/apps/server/src/workspace/WorkspaceSearchIndex.ts @@ -552,7 +552,7 @@ function parseWorkspaceSearchIndexKey(key: string): { * idle cleanup; using a default cwd here would mix resources from different * workspaces. */ -export const layer = (key: string) => { +const layer = (key: string) => { const { cwd, variant } = parseWorkspaceSearchIndexKey(key); return Layer.effect(WorkspaceSearchIndex, make(cwd, variant)); }; diff --git a/apps/web/src/browser/browserDefaults.ts b/apps/web/src/browser/browserDefaults.ts index 6141b1a52fa9..5b6d6ed57bfd 100644 --- a/apps/web/src/browser/browserDefaults.ts +++ b/apps/web/src/browser/browserDefaults.ts @@ -128,7 +128,7 @@ export function browserDefaultOpenProfileId( * fall back to fitting the panel — and only when the panel hasn't been measured * yet does a fixed size apply. */ -export const FALLBACK_RESPONSIVE_VIEWPORT_SIZE = { width: 1024, height: 768 } as const; +const FALLBACK_RESPONSIVE_VIEWPORT_SIZE = { width: 1024, height: 768 } as const; export function browserResponsiveViewportForToggle(input: { readonly defaults?: BrowserDefaults; diff --git a/infra/relay/scripts/deploy.ts b/infra/relay/scripts/deploy.ts index 1942b8735e37..52fdfec8edec 100644 --- a/infra/relay/scripts/deploy.ts +++ b/infra/relay/scripts/deploy.ts @@ -130,22 +130,6 @@ export function reconcileRootEnvPublicConfig(contents: string, config: RelayPubl return next; } -export function reconcileRootEnvRelayUrl(contents: string, relayUrl: string): string { - return reconcileRootEnvPublicConfig(contents, { - relayUrl, - mobileTracingUrl: "", - mobileTracingDataset: "", - mobileTracingToken: "", - clientTracingUrl: "", - clientTracingDataset: "", - clientTracingToken: "", - }) - .split("\n") - .filter((line) => !line.startsWith("T3CODE_MOBILE_OTLP_TRACES_")) - .filter((line) => !line.startsWith("T3CODE_RELAY_CLIENT_OTLP_TRACES_")) - .join("\n"); -} - export function hasDeployChanges(plan: Plan.Plan): boolean { return ( Object.keys(plan.deletions).length > 0 || @@ -425,7 +409,7 @@ const runRelayDeploy = Effect.fn("relay.deploy.run")( ), ); -export const deploy = Effect.fn("relay.deploy")(function* (options: RelayDeployOptions) { +const deploy = Effect.fn("relay.deploy")(function* (options: RelayDeployOptions) { const configProvider = yield* loadDeployConfigProvider(options.envFile); const configuredStage = yield* relayDeployStage.pipe( Effect.provide(ConfigProvider.layer(configProvider)), @@ -445,7 +429,7 @@ export const deploy = Effect.fn("relay.deploy")(function* (options: RelayDeployO } }); -export const relayDeployCommand = Command.make( +const relayDeployCommand = Command.make( "relay-deploy", { dryRun: Flag.boolean("dry-run").pipe( diff --git a/infra/relay/src/Config.ts b/infra/relay/src/Config.ts index e7c7d42f2ae1..2991e442d4b0 100644 --- a/infra/relay/src/Config.ts +++ b/infra/relay/src/Config.ts @@ -30,6 +30,7 @@ export class RelayConfiguration extends Context.Service< } >()("t3code-relay/Config/RelayConfiguration") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = (configuration: RelayConfiguration["Service"]) => RelayConfiguration.of(configuration); diff --git a/infra/relay/src/agentActivity/AgentActivityPublisher.ts b/infra/relay/src/agentActivity/AgentActivityPublisher.ts index 05ad4fd87b14..6d91ca5c3824 100644 --- a/infra/relay/src/agentActivity/AgentActivityPublisher.ts +++ b/infra/relay/src/agentActivity/AgentActivityPublisher.ts @@ -47,6 +47,7 @@ export class AgentActivityPublisher extends Context.Service< } >()("t3code-relay/agentActivity/AgentActivityPublisher") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const rows = yield* AgentActivityRows.AgentActivityRows; const links = yield* EnvironmentLinks.EnvironmentLinks; @@ -231,7 +232,7 @@ function terminalAggregateState(state: RelayAgentActivityState): RelayAgentActiv // How long a finished thread keeps its Done/Failed row in the aggregate while // other agents are still active. Long enough to be seen on the lock screen, // short enough that the activity list stays about live work. -export const TERMINAL_AGENT_ACTIVITY_DISPLAY_TTL_MS = 15 * 60 * 1_000; +const TERMINAL_AGENT_ACTIVITY_DISPLAY_TTL_MS = 15 * 60 * 1_000; function isRecentTerminalState(state: RelayAgentActivityState, nowMs: number): boolean { if (!isTerminalPhase(state)) { diff --git a/infra/relay/src/agentActivity/AgentActivityRows.ts b/infra/relay/src/agentActivity/AgentActivityRows.ts index 032a61a383ef..bd816e21dd2b 100644 --- a/infra/relay/src/agentActivity/AgentActivityRows.ts +++ b/infra/relay/src/agentActivity/AgentActivityRows.ts @@ -99,6 +99,7 @@ const encodeRelayAgentActivityStateJson = Schema.encodeEffect( const decodeRelayAgentActivityState = Schema.decodeUnknownOption(RelayAgentActivityStateSchema); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const db = yield* RelayDb.RelayDb; diff --git a/infra/relay/src/agentActivity/ApnsClient.ts b/infra/relay/src/agentActivity/ApnsClient.ts index 4276b7062555..3ac046dd2f5a 100644 --- a/infra/relay/src/agentActivity/ApnsClient.ts +++ b/infra/relay/src/agentActivity/ApnsClient.ts @@ -223,6 +223,7 @@ export class ApnsClient extends Context.Service< } >()("t3code-relay/agentActivity/ApnsClient") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const httpClient = yield* HttpClient.HttpClient; const providerTokens = yield* ApnsProviderTokens.ApnsProviderTokens; diff --git a/infra/relay/src/agentActivity/ApnsDeliveries.ts b/infra/relay/src/agentActivity/ApnsDeliveries.ts index 9db9be3f1681..932570613d97 100644 --- a/infra/relay/src/agentActivity/ApnsDeliveries.ts +++ b/infra/relay/src/agentActivity/ApnsDeliveries.ts @@ -692,6 +692,7 @@ export class ApnsDeliveries extends Context.Service< } >()("t3code-relay/agentActivity/ApnsDeliveries") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const attempts = yield* DeliveryAttempts.DeliveryAttempts; const liveActivities = yield* LiveActivities.LiveActivities; diff --git a/infra/relay/src/agentActivity/ApnsDeliveryQueue.ts b/infra/relay/src/agentActivity/ApnsDeliveryQueue.ts index 2a1d6abba3ea..0a8a2f2ebcf6 100644 --- a/infra/relay/src/agentActivity/ApnsDeliveryQueue.ts +++ b/infra/relay/src/agentActivity/ApnsDeliveryQueue.ts @@ -76,6 +76,7 @@ export class ApnsDeliveryQueue extends Context.Service< } >()("t3code-relay/agentActivity/ApnsDeliveryQueue") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const sender = yield* ApnsDeliveryQueueSender; const crypto = yield* Crypto.Crypto; diff --git a/infra/relay/src/agentActivity/ApnsProviderTokens.ts b/infra/relay/src/agentActivity/ApnsProviderTokens.ts index 329f07283200..ac1c5247a5d0 100644 --- a/infra/relay/src/agentActivity/ApnsProviderTokens.ts +++ b/infra/relay/src/agentActivity/ApnsProviderTokens.ts @@ -41,10 +41,11 @@ export function __resetApnsProviderTokenCacheForTest(): void { // Quantize iat to the reuse window so all isolates agree on it. The token's // age stays under APNs' 60-minute limit, and the whole fleet rolls to the // next token at the same instant — one provider-token update per window. -export function quantizedApnsJwtIssuedAt(nowUnixSeconds: number): number { +function quantizedApnsJwtIssuedAt(nowUnixSeconds: number): number { return Math.floor(nowUnixSeconds / APNS_JWT_REUSE_SECONDS) * APNS_JWT_REUSE_SECONDS; } +/** @public Service construction is part of the module API alongside layer. */ export const make = () => ApnsProviderTokens.of({ getJwt: Effect.fnUntraced(function* (input) { diff --git a/infra/relay/src/agentActivity/DeliveryAttempts.ts b/infra/relay/src/agentActivity/DeliveryAttempts.ts index 843415abfe87..dbc4627b6fc1 100644 --- a/infra/relay/src/agentActivity/DeliveryAttempts.ts +++ b/infra/relay/src/agentActivity/DeliveryAttempts.ts @@ -91,6 +91,7 @@ function insertValues( }; } +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const db = yield* RelayDb.RelayDb; const crypto = yield* Crypto.Crypto; diff --git a/infra/relay/src/agentActivity/Devices.ts b/infra/relay/src/agentActivity/Devices.ts index 42087128c331..6e646916e972 100644 --- a/infra/relay/src/agentActivity/Devices.ts +++ b/infra/relay/src/agentActivity/Devices.ts @@ -70,6 +70,7 @@ export class Devices extends Context.Service< } >()("t3code-relay/agentActivity/Devices") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const db = yield* RelayDb.RelayDb; diff --git a/infra/relay/src/agentActivity/LiveActivities.ts b/infra/relay/src/agentActivity/LiveActivities.ts index a2179e1e7693..b502ac6c97cc 100644 --- a/infra/relay/src/agentActivity/LiveActivities.ts +++ b/infra/relay/src/agentActivity/LiveActivities.ts @@ -129,6 +129,7 @@ const encodeRelayAgentActivityAggregateStateJson = Schema.encodeEffect( Schema.fromJsonString(RelayAgentActivityAggregateStateSchema), ); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const db = yield* RelayDb.RelayDb; diff --git a/infra/relay/src/agentActivity/MobileRegistrations.ts b/infra/relay/src/agentActivity/MobileRegistrations.ts index aee83e4b06db..5148b7d1f439 100644 --- a/infra/relay/src/agentActivity/MobileRegistrations.ts +++ b/infra/relay/src/agentActivity/MobileRegistrations.ts @@ -40,6 +40,7 @@ export class MobileRegistrations extends Context.Service< } >()("t3code-relay/agentActivity/MobileRegistrations") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const rows = yield* AgentActivityRows.AgentActivityRows; const devices = yield* Devices.Devices; diff --git a/infra/relay/src/agentActivity/agentActivityPayloads.ts b/infra/relay/src/agentActivity/agentActivityPayloads.ts index a5e12a4be438..d9b5115c3e2d 100644 --- a/infra/relay/src/agentActivity/agentActivityPayloads.ts +++ b/infra/relay/src/agentActivity/agentActivityPayloads.ts @@ -63,7 +63,7 @@ function sanitizeDeepLink(value: string): string { return truncateText(trimmed, MAX_DEEP_LINK_LENGTH); } -export function sanitizeAgentActivityAggregateRow( +function sanitizeAgentActivityAggregateRow( row: RelayAgentActivityAggregateRow, ): RelayAgentActivityAggregateRow { return { diff --git a/infra/relay/src/agentActivity/apnsDeliveryJobs.ts b/infra/relay/src/agentActivity/apnsDeliveryJobs.ts index 256ca3edb5ca..b6fb2d214847 100644 --- a/infra/relay/src/agentActivity/apnsDeliveryJobs.ts +++ b/infra/relay/src/agentActivity/apnsDeliveryJobs.ts @@ -12,7 +12,7 @@ import * as Redacted from "effect/Redacted"; import * as Schema from "effect/Schema"; const MAX_JOB_AGE_MS = 10 * 60 * 1_000; -export const APNS_DELIVERY_JOB_SIGNING_ALGORITHM = "hmac-sha256"; +const APNS_DELIVERY_JOB_SIGNING_ALGORITHM = "hmac-sha256"; const ApnsDeliveryKindSchema = Schema.Literals([ "live_activity_start", diff --git a/infra/relay/src/environments/ManagedEndpointAllocations.ts b/infra/relay/src/environments/ManagedEndpointAllocations.ts index 4320eeea3b72..a45ec2162d71 100644 --- a/infra/relay/src/environments/ManagedEndpointAllocations.ts +++ b/infra/relay/src/environments/ManagedEndpointAllocations.ts @@ -165,6 +165,7 @@ const whereAllocation = (input: ManagedEndpointAllocationKey) => eq(relayManagedEndpointAllocations.environmentId, input.environmentId), ); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const db = yield* RelayDb.RelayDb; diff --git a/infra/relay/src/environments/ManagedEndpointProvider.ts b/infra/relay/src/environments/ManagedEndpointProvider.ts index 9a578874844e..9f2bd5578462 100644 --- a/infra/relay/src/environments/ManagedEndpointProvider.ts +++ b/infra/relay/src/environments/ManagedEndpointProvider.ts @@ -361,6 +361,7 @@ const ignoreNotFound = ( }), ); +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const config = yield* RelayConfiguration.RelayConfiguration; const crypto = yield* Crypto.Crypto; diff --git a/infra/relay/src/environments/ManagedTunnelLimits.ts b/infra/relay/src/environments/ManagedTunnelLimits.ts index 9d8b9c796ed6..d6d3ae980481 100644 --- a/infra/relay/src/environments/ManagedTunnelLimits.ts +++ b/infra/relay/src/environments/ManagedTunnelLimits.ts @@ -54,6 +54,7 @@ export class ManagedTunnelLimits extends Context.Service< } >()("t3code-relay/environments/ManagedTunnelLimits") {} +/** @public Service construction is part of the module API alongside layer. */ export const make = Effect.gen(function* () { const db = yield* RelayDb.RelayDb; diff --git a/infra/relay/src/http/Api.ts b/infra/relay/src/http/Api.ts index 05197666c80d..6e581afff1f4 100644 --- a/infra/relay/src/http/Api.ts +++ b/infra/relay/src/http/Api.ts @@ -199,7 +199,7 @@ const relayRequestDeadline = ( ), ); -export const traceRelayHttpRequest = ( +const traceRelayHttpRequest = ( httpEffect: Effect.Effect< HttpServerResponse.HttpServerResponse, E, diff --git a/infra/relay/src/worker.ts b/infra/relay/src/worker.ts index 77dfd845c5bc..a52461adb2e7 100644 --- a/infra/relay/src/worker.ts +++ b/infra/relay/src/worker.ts @@ -98,7 +98,7 @@ const ApnsDeliveryJobSigningSecret = Alchemy.makeRandom("ApnsDeliveryJobSigningS export class Api extends Cloudflare.Worker()("Api") {} -export const ApiLive = Api.make( +const ApiLive = Api.make( RelayDeploymentConfig.pipe( Effect.map(({ relayPublicDomain }) => ({ main: import.meta.filename, diff --git a/knip.jsonc b/knip.jsonc index c6ba319da5b1..3ba3fbd3872e 100644 --- a/knip.jsonc +++ b/knip.jsonc @@ -4,6 +4,8 @@ "rules": { "types": "off", "nsTypes": "off" }, // These executables are supplied by the OS or installed separately from npm. "ignoreBinaries": ["eas", "file", "mkfifo", "pkill", "pkg-config", "plutil", "sips"], + // @effect/tsgo embeds the language service and reads this tsconfig plugin key. + "ignoreDependencies": ["@effect/language-service"], "workspaces": { ".": { // Keep vendored reference repositories outside the root project. @@ -22,6 +24,8 @@ "src/bin.ts!", "src/service-launcher.ts!", "scripts/cli.ts", + // Invoked directly by the test-t3-app skill for isolated SQLite fixtures. + "scripts/t3-sqlite-state.ts", "src/provider/testFixtures/*.mjs", ], // Native msgpack acceleration and the Vite+ web build prerequisite. @@ -49,6 +53,8 @@ "ignoreIssues": { "src/components/ui/*.tsx": ["exports", "nsExports", "duplicates"] }, }, "apps/mobile": { + // Expo uses Babel without a direct @babel/* dependency to enable this plugin. + "babel": true, // Expo loads local config plugins by string; Metro handles platform variants. "entry": ["index.ts!", "plugins/*.cjs"], // Fonts are configured as asset paths; Expo autolinks the native packages. diff --git a/patches/knip@6.34.0.patch b/patches/knip@6.34.0.patch new file mode 100644 index 000000000000..150c9f043d81 --- /dev/null +++ b/patches/knip@6.34.0.patch @@ -0,0 +1,244 @@ +diff --git a/dist/CatalogCounselor.d.ts b/dist/CatalogCounselor.d.ts +index ac7cb0db0ed7715141b667bc6104471e421134b0..5e07e3915ca4bd1f206adb6492c0b6be0a633aa0 100644 +--- a/dist/CatalogCounselor.d.ts ++++ b/dist/CatalogCounselor.d.ts +@@ -6,12 +6,14 @@ export type CatalogContainer = { + filePath: string; + catalog?: Catalog; + catalogs?: Catalogs; ++ overrides?: Catalog; + }; + export declare class CatalogCounselor { + private filePath; + private entries; + private referencedEntries; + private referenceIssues; ++ private overrideReferences; + private fileContent?; + constructor(options: MainOptions); + private addReferencedCatalogEntry; +diff --git a/dist/CatalogCounselor.js b/dist/CatalogCounselor.js +index 85df4b6add89e5f11368604e830757e794b328bf..6f73b4ce294373ba40088d74f33671ac7dc64830 100644 +--- a/dist/CatalogCounselor.js ++++ b/dist/CatalogCounselor.js +@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises'; + import { ROOT_WORKSPACE_NAME } from './constants.js'; + import { JsonCatalogPeeker } from './JsonCatalogPeeker.js'; + import { PackagePeeker } from './PackagePeeker.js'; +-import { extractCatalogReferences, parseCatalog } from './util/catalog.js'; ++import { extractCatalogReferences, getOverrideCatalogReferences, parseCatalog, } from './util/catalog.js'; + import { extname } from './util/path.js'; + import { YamlCatalogPeeker } from './YamlCatalogPeeker.js'; + export class CatalogCounselor { +@@ -10,10 +10,14 @@ export class CatalogCounselor { + entries = new Set(); + referencedEntries = new Set(); + referenceIssues = []; ++ overrideReferences = []; + fileContent; + constructor(options) { + this.filePath = options.catalog.filePath; + this.entries = parseCatalog(options.catalog); ++ this.overrideReferences = getOverrideCatalogReferences(options.catalog.overrides); ++ for (const reference of this.overrideReferences) ++ this.addReference(reference); + } + addReferencedCatalogEntry(entryName) { + this.referencedEntries.add(entryName); +@@ -23,14 +27,18 @@ export class CatalogCounselor { + } + addWorkspace({ name: workspace, manifest, manifestPath: filePath, manifestStr, }) { + const catalogReferences = extractCatalogReferences(manifest); ++ if (workspace === ROOT_WORKSPACE_NAME) { ++ for (const reference of getOverrideCatalogReferences(manifest.pnpm?.overrides)) ++ catalogReferences.push(reference); ++ } + if (catalogReferences.length === 0) + return; + const peeker = new PackagePeeker(manifestStr); +- for (const { catalogName, packageName } of catalogReferences) { ++ for (const { catalogName, packageName, selector } of catalogReferences) { + const catalogEntryName = `${catalogName}:${packageName}`; + this.addReferencedCatalogEntry(catalogEntryName); + if (!this.entries.has(catalogEntryName)) { +- const pos = peeker.getCatalogReferenceLocation(packageName, catalogName); ++ const pos = peeker.getCatalogReferenceLocation(selector ?? packageName, catalogName); + this.referenceIssues.push({ + type: 'catalogReferences', + filePath, +@@ -47,11 +55,12 @@ export class CatalogCounselor { + const filePath = this.filePath; + const workspace = ROOT_WORKSPACE_NAME; + const catalogIssues = []; +- if (this.entries.size > 0) { ++ const overrideReferenceIssues = []; ++ if (this.entries.size > 0 || this.overrideReferences.length > 0) { + this.fileContent = await readFile(filePath, 'utf-8'); + const isYaml = ['.yml', '.yaml'].includes(extname(filePath)); +- const Peeker = isYaml ? YamlCatalogPeeker : JsonCatalogPeeker; +- const peeker = new Peeker(this.fileContent); ++ const yamlPeeker = isYaml ? new YamlCatalogPeeker(this.fileContent) : undefined; ++ const peeker = yamlPeeker ?? new JsonCatalogPeeker(this.fileContent); + for (const entry of this.entries.keys()) { + if (!this.referencedEntries.has(entry)) { + const [parentSymbol, symbol] = entry.split(':'); +@@ -62,7 +71,21 @@ export class CatalogCounselor { + catalogIssues.push({ type: 'catalog', filePath, workspace, symbol, parentSymbol, fixes, ...pos }); + } + } ++ for (const { catalogName, packageName, selector } of this.overrideReferences) { ++ if (this.entries.has(`${catalogName}:${packageName}`)) ++ continue; ++ const pos = yamlPeeker?.getOverrideCatalogReferenceLocation(selector); ++ overrideReferenceIssues.push({ ++ type: 'catalogReferences', ++ filePath, ++ workspace, ++ symbol: packageName, ++ parentSymbol: catalogName, ++ fixes: [], ++ ...pos, ++ }); ++ } + } +- return [...catalogIssues, ...this.referenceIssues]; ++ return [...catalogIssues, ...this.referenceIssues, ...overrideReferenceIssues]; + } + } +diff --git a/dist/YamlCatalogPeeker.d.ts b/dist/YamlCatalogPeeker.d.ts +index 30c12ce90e6fc4d408b13a6ade12e992a138af3a..957d5e911ac2ad97bd0bce02cf3f261f4f5fbad2 100644 +--- a/dist/YamlCatalogPeeker.d.ts ++++ b/dist/YamlCatalogPeeker.d.ts +@@ -9,4 +9,8 @@ export declare class YamlCatalogPeeker { + line: number; + col: number; + } | undefined; ++ getOverrideCatalogReferenceLocation(selector: string): { ++ line: number; ++ col: number; ++ } | undefined; + } +diff --git a/dist/YamlCatalogPeeker.js b/dist/YamlCatalogPeeker.js +index a3660dbbb16cc33937fc02834e7581132ea47bef..5901f4cf413951320df65078201ae0ebb9e7119c 100644 +--- a/dist/YamlCatalogPeeker.js ++++ b/dist/YamlCatalogPeeker.js +@@ -22,6 +22,9 @@ export class YamlCatalogPeeker { + else if (line.startsWith('catalogs:')) { + this.sections.catalogs = i; + } ++ else if (line.startsWith('overrides:')) { ++ this.sections.overrides = i; ++ } + } + this.ready = true; + } +@@ -63,4 +66,18 @@ export class YamlCatalogPeeker { + } + } + } ++ getOverrideCatalogReferenceLocation(selector) { ++ if (!this.ready) ++ this.init(); ++ const startLine = this.sections.overrides; ++ if (typeof startLine === 'undefined') ++ return; ++ for (let i = startLine + 1; i < this.lines.length; i++) { ++ const line = this.lines[i]; ++ if (!line.startsWith(' ')) ++ break; ++ if (matchesKey(line, ' ', selector)) ++ return { line: i + 1, col: line.indexOf(selector) + 1 }; ++ } ++ } + } +diff --git a/dist/util/catalog.d.ts b/dist/util/catalog.d.ts +index 1788b677af9934b410507fcad85c158c87c1c176..115698d0cf537d3849e5ad469065a396d3da3b5d 100644 +--- a/dist/util/catalog.d.ts ++++ b/dist/util/catalog.d.ts +@@ -4,8 +4,13 @@ export declare const DEFAULT_CATALOG = "default"; + export type CatalogReference = { + catalogName: string; + packageName: string; ++ selector?: string; ++}; ++export type OverrideCatalogReference = CatalogReference & { ++ selector: string; + }; + export declare const getCatalogReference: (specifier: string) => CatalogReference | undefined; + export declare const getCatalogContainer: (cwd: string, manifest: PackageJson, manifestPath: string, pnpmWorkspacePath?: string, pnpmWorkspace?: any) => Promise; + export declare const parseCatalog: (container: CatalogContainer) => Set; ++export declare const getOverrideCatalogReferences: (overrides: Record | undefined) => OverrideCatalogReference[]; + export declare const extractCatalogReferences: (manifest: PackageJson) => CatalogReference[]; +diff --git a/dist/util/catalog.js b/dist/util/catalog.js +index 9616152aead2b349d06bb21f3ebd509bf583aed8..2b07ba27976a963ea41358dd934f29a81c7aa9b6 100644 +--- a/dist/util/catalog.js ++++ b/dist/util/catalog.js +@@ -27,7 +27,7 @@ export const getCatalogContainer = async (cwd, manifest, manifestPath, pnpmWorks + yarnWorkspace?.catalogs ?? + manifest.catalogs ?? + ((!Array.isArray(manifest.workspaces) && manifest.workspaces?.catalogs) || {}); +- return { filePath, catalog, catalogs }; ++ return { filePath, catalog, catalogs, overrides: pnpmWorkspace?.overrides }; + }; + const extractEntries = (catalog) => { + if (catalog && typeof catalog === 'object') +@@ -56,23 +56,43 @@ export const parseCatalog = (container) => { + entries.add(id); + return entries; + }; ++const OVERRIDE_DELIMITER = /[^ |@]>/; ++const toCatalogReference = (packageName, version) => { ++ if (typeof version !== 'string' || !version.startsWith('catalog:')) ++ return; ++ return { catalogName: version.slice('catalog:'.length) || DEFAULT_CATALOG, packageName }; ++}; ++const collectCatalogReferences = (dependencies, catalogReferences) => { ++ if (!dependencies) ++ return; ++ for (const [packageName, version] of Object.entries(dependencies)) { ++ const reference = toCatalogReference(packageName, version); ++ if (reference) ++ catalogReferences.push(reference); ++ } ++}; ++export const getOverrideCatalogReferences = (overrides) => { ++ const catalogReferences = []; ++ if (!overrides) ++ return catalogReferences; ++ for (const [selector, version] of Object.entries(overrides)) { ++ const delimiterIndex = selector.search(OVERRIDE_DELIMITER); ++ const target = delimiterIndex === -1 ? selector : selector.slice(delimiterIndex + 2); ++ const packageName = getPackageNameFromModuleSpecifier(target); ++ if (!packageName) ++ continue; ++ const reference = toCatalogReference(packageName, version); ++ if (reference) ++ catalogReferences.push({ ...reference, selector }); ++ } ++ return catalogReferences; ++}; + export const extractCatalogReferences = (manifest) => { + const catalogReferences = []; +- const checkDependencies = (dependencies) => { +- if (!dependencies) +- return; +- for (const [name, version] of Object.entries(dependencies)) { +- if (typeof version === 'string' && version.startsWith('catalog:')) { +- const catalogName = version.slice('catalog:'.length) || DEFAULT_CATALOG; +- catalogReferences.push({ catalogName, packageName: name }); +- } +- } +- }; +- checkDependencies(manifest.dependencies); +- checkDependencies(manifest.devDependencies); +- checkDependencies(manifest.peerDependencies); +- checkDependencies(manifest.optionalDependencies); +- checkDependencies(manifest.resolutions); +- checkDependencies(manifest.pnpm?.overrides); ++ collectCatalogReferences(manifest.dependencies, catalogReferences); ++ collectCatalogReferences(manifest.devDependencies, catalogReferences); ++ collectCatalogReferences(manifest.peerDependencies, catalogReferences); ++ collectCatalogReferences(manifest.optionalDependencies, catalogReferences); ++ collectCatalogReferences(manifest.resolutions, catalogReferences); + return catalogReferences; + }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95403e871a9b..d42d0bd210bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,6 +100,7 @@ patchedDependencies: expo-audio@57.0.4: fa9a3e0442ed395d4071bb406e08c3a471c9a84700bdfa0b9ad7ff144c96041a expo-sharing@57.0.17: 8d2e3b10eb3f52036a9a086800180ec6cebf3b75bccc5b1775117a7244d4ac45 react-native-gesture-handler@2.32.0: 96573c000f7fe56b5abfa13e2e5f0d065907e674cb8e2300155226d7c9874398 + knip@6.34.0: 4332f0da187c57766fcaf5689c3bf756264b3153b7d3f67ebaba17f48ab489b0 react-native-keyboard-controller@1.21.13: 6e4339347bc5bb3c9ea67d85ff5c814058b211c5750f247aba59d07869a2e787 react-native-nitro-modules@0.35.9: 825622aae63a8fb5b904f3c77908a0e216261d727ea171709f2c0b6088422675 react-native-screens@4.26.2: 8156dd0f3407822404793cfdaa95639a36b62102f4507c981b8be83600bb382d @@ -120,7 +121,7 @@ importers: version: 7.0.0-dev.20260604.1 knip: specifier: 6.34.0 - version: 6.34.0 + version: 6.34.0(patch_hash=4332f0da187c57766fcaf5689c3bf756264b3153b7d3f67ebaba17f48ab489b0) vite-plus: specifier: 'catalog:' version: 0.3.0(@types/node@24.12.4)(bufferutil@4.1.0)(esbuild@0.28.1)(jiti@2.7.0)(msw@2.12.11(@types/node@24.12.4)(typescript@6.0.3))(terser@5.48.0)(typescript@6.0.3)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) @@ -387,6 +388,9 @@ importers: expo-symbols: specifier: ~57.0.2 version: 57.0.2(expo-font@57.0.2(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3))(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) + expo-system-ui: + specifier: ~57.0.3 + version: 57.0.3(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6)) expo-updates: specifier: ~57.0.19 version: 57.0.19(expo-dev-client@57.0.16(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6)))(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3) @@ -7087,6 +7091,16 @@ packages: react: '*' react-native: '*' + expo-system-ui@57.0.3: + resolution: {integrity: sha512-3N3BoagGojEvQw0h7kL0Lvv2LrVjqEvODSNS+Nc9lj/kzaTaVx4K1HI8qqxeALMf5jui3rLP2b3Ai2pXotoNuA==} + peerDependencies: + expo: '*' + react-native: '*' + react-native-web: '*' + peerDependenciesMeta: + react-native-web: + optional: true + expo-updates-interface@57.0.1: resolution: {integrity: sha512-+LUWwJ0gf/TEKMVdQAw/Gjih4dvrk+URgy24X9qEGKuuMDZqjBRm9T4yQyBVALGL5TTdPUaB6ILxx3lshm3pwQ==} peerDependencies: @@ -17249,6 +17263,15 @@ snapshots: react-native: 0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6) sf-symbols-typescript: 2.2.0 + expo-system-ui@57.0.3(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6)): + dependencies: + '@react-native/normalize-colors': 0.86.3 + debug: 4.4.3 + expo: 57.0.18(f9c992a5d7c53d81398568d3950992dc) + react-native: 0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - supports-color + expo-updates-interface@57.0.1(expo@57.0.18): dependencies: expo: 57.0.18(f9c992a5d7c53d81398568d3950992dc) @@ -18249,7 +18272,7 @@ snapshots: kleur@4.1.5: {} - knip@6.34.0: + knip@6.34.0(patch_hash=4332f0da187c57766fcaf5689c3bf756264b3153b7d3f67ebaba17f48ab489b0): dependencies: fdir: 6.5.0(picomatch@4.0.7) formatly: 0.7.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ee1bd25547f6..461e2b41f0ae 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -169,6 +169,8 @@ patchedDependencies: effect@4.0.0-beta.103: patches/effect@4.0.0-beta.103.patch expo-audio@57.0.4: patches/expo-audio@57.0.4.patch expo-sharing@57.0.17: patches/expo-sharing@57.0.17.patch + # Compiled backport of https://github.com/webpro-nl/knip/commit/c6497a18c6534ee914b27bb459d7778a7b93a914 + knip@6.34.0: patches/knip@6.34.0.patch react-native-gesture-handler@2.32.0: patches/react-native-gesture-handler@2.32.0.patch react-native-keyboard-controller@1.21.13: patches/react-native-keyboard-controller@1.21.13.patch react-native-nitro-modules@0.35.9: patches/react-native-nitro-modules@0.35.9.patch diff --git a/scripts/apply-web-brand-assets.ts b/scripts/apply-web-brand-assets.ts index 30e6bc325b6c..ece9a15fd58a 100644 --- a/scripts/apply-web-brand-assets.ts +++ b/scripts/apply-web-brand-assets.ts @@ -39,7 +39,7 @@ export const applyWebBrandAssets = Effect.fn("applyWebBrandAssets")(function* ( ); }); -export const applyWebBrandAssetsCommand = Command.make( +const applyWebBrandAssetsCommand = Command.make( "apply-web-brand-assets", { brand: Argument.choice("brand", WEB_ASSET_BRANDS).pipe( diff --git a/scripts/knip-catalogs.test.ts b/scripts/knip-catalogs.test.ts new file mode 100644 index 000000000000..7edcba8ff85c --- /dev/null +++ b/scripts/knip-catalogs.test.ts @@ -0,0 +1,87 @@ +// @effect-diagnostics nodeBuiltinImport:off - Exercises the patched Knip CLI against a disposable project. +import * as NodeChildProcess from "node:child_process"; +import * as NodeFS from "node:fs"; +import * as NodeModule from "node:module"; +import * as NodeOS from "node:os"; +import * as NodePath from "node:path"; +import * as NodeProcess from "node:process"; +import { expect, it } from "vite-plus/test"; + +const require = NodeModule.createRequire(import.meta.url); +const cli = NodePath.join(NodePath.dirname(require.resolve("knip")), "cli.js"); + +it("counts pnpm workspace overrides without hiding unused or missing catalog entries", () => { + const cwd = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-knip-catalogs-")); + const write = (file: string, content: string) => + NodeFS.writeFileSync(NodePath.join(cwd, file), content); + const run = () => + NodeChildProcess.spawnSync( + NodeProcess.execPath, + [ + cli, + "--directory", + cwd, + "--include", + "catalog,catalogReferences", + "--reporter", + "json", + "--no-config-hints", + ], + { encoding: "utf8" }, + ); + const workspace = `packages: [] +catalog: + override-only: 1.0.0 + version-range: 1.0.0 + legacy: 1.0.0 + unused: 1.0.0 +catalogs: + native: + '@scope/native': 2.0.0 +overrides: + override-only: 'catalog:' + 'version-range@>=1': 'catalog:' + 'parent@1>@scope/native@2': 'catalog:native' + missing: 'catalog:' + plain-version: 3.0.0 +`; + try { + write( + "package.json", + JSON.stringify({ + name: "catalog-fixture", + private: true, + pnpm: { overrides: { "parent@>=1>legacy@>=1": "catalog:" } }, + }), + ); + write("knip.json", JSON.stringify({ entry: ["index.js"], project: ["index.js"] })); + write("index.js", "console.log('fixture');\n"); + write("pnpm-workspace.yaml", workspace); + + const findings = run(); + expect(findings.status, findings.stderr).toBe(1); + expect(JSON.parse(findings.stdout).issues).toEqual([ + expect.objectContaining({ + file: "pnpm-workspace.yaml", + catalog: [expect.objectContaining({ name: "unused" })], + catalogReferences: [ + expect.objectContaining({ + name: "missing", + line: workspace.split("\n").findIndex((line) => line.startsWith(" missing:")) + 1, + col: 3, + }), + ], + }), + ]); + + write( + "pnpm-workspace.yaml", + workspace.replace(" unused: 1.0.0\n", "").replace(" missing: 'catalog:'\n", ""), + ); + const clean = run(); + expect(clean.status, clean.stderr + clean.stdout).toBe(0); + expect(JSON.parse(clean.stdout).issues).toEqual([]); + } finally { + NodeFS.rmSync(cwd, { recursive: true, force: true }); + } +}); diff --git a/scripts/lib/cli-external-packages.ts b/scripts/lib/cli-external-packages.ts index d7a89bc408a4..a08a04fac861 100644 --- a/scripts/lib/cli-external-packages.ts +++ b/scripts/lib/cli-external-packages.ts @@ -58,17 +58,17 @@ export const CLI_RUNTIME_EXTERNAL_PREFIXES = [ * bundling for Node. Because Node never loads them, their dependency closure * does not need to be external — only the entry point must stay unbundled. */ -export const CLI_BUILD_ONLY_EXTERNAL_PREFIXES = [ +const CLI_BUILD_ONLY_EXTERNAL_PREFIXES = [ "@effect/platform-bun", "@effect/sql-sqlite-bun", ] as const; -export const CLI_EXTERNAL_PACKAGE_PREFIXES = [ +const CLI_EXTERNAL_PACKAGE_PREFIXES = [ ...CLI_RUNTIME_EXTERNAL_PREFIXES, ...CLI_BUILD_ONLY_EXTERNAL_PREFIXES, ] as const; -export function isRuntimeExternalCliDependency(id: string): boolean { +function isRuntimeExternalCliDependency(id: string): boolean { return CLI_RUNTIME_EXTERNAL_PREFIXES.some((prefix) => id.startsWith(prefix)); } diff --git a/scripts/lib/dev-share.ts b/scripts/lib/dev-share.ts index e3fb884eb836..62f5ef1c368e 100644 --- a/scripts/lib/dev-share.ts +++ b/scripts/lib/dev-share.ts @@ -116,7 +116,6 @@ export const DevShareError = Schema.Union([ DevServeFailedError, ]); export type DevShareError = typeof DevShareError.Type; -export const isDevShareError = Schema.is(DevShareError); /** * Removes any mapping for `webPort`, reporting whether the port is now clear. diff --git a/scripts/mobile-showcase-environment.ts b/scripts/mobile-showcase-environment.ts index 93738b61325a..74e8b1e4d06a 100644 --- a/scripts/mobile-showcase-environment.ts +++ b/scripts/mobile-showcase-environment.ts @@ -7,7 +7,7 @@ import * as NodeUtil from "node:util"; const execFile = NodeUtil.promisify(NodeChildProcess.execFile); -export const SHOWCASE_PROJECT_ID = "t3code"; +const SHOWCASE_PROJECT_ID = "t3code"; export const SHOWCASE_THREAD_ID = "remote-command-center"; export const SHOWCASE_TERMINAL_ID = "term-1"; @@ -51,7 +51,7 @@ const SHOWCASE_TERMINAL_PROMPT = // zsh-style prompt, brand line, addresses, the thread's 612-test summary, // and a READY badge, so the scene exercises bold, dim, underline, the six // accent colors, and a background cell. -export const SHOWCASE_TERMINAL_BUFFER = [ +const SHOWCASE_TERMINAL_BUFFER = [ `${SHOWCASE_TERMINAL_PROMPT}vpr dev`, "", " \u001b[1;32mVITE\u001b[0m \u001b[32mv7.1.1\u001b[0m \u001b[2mready in\u001b[0m \u001b[1m1.24s\u001b[0m",