From 7323b05f426868ec6228af0cbf396ad10527a7a6 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 13:53:30 -0700 Subject: [PATCH 01/10] Migrate repository TypeScript catalog to 6.0.3 Co-authored-by: codex --- apps/server/tsconfig.json | 1 - bun.lock | 7 +++++-- package.json | 2 +- packages/contracts/package.json | 1 + packages/contracts/src/orchestration.test.ts | 4 +++- packages/contracts/tsconfig.json | 4 +++- packages/effect-acp/package.json | 1 + packages/effect-acp/tsconfig.json | 4 +++- packages/effect-codex-app-server/package.json | 1 + packages/effect-codex-app-server/tsconfig.json | 4 +++- packages/shared/tsconfig.json | 4 +++- packages/ssh/tsconfig.json | 4 +++- packages/tailscale/tsconfig.json | 4 +++- 13 files changed, 30 insertions(+), 11 deletions(-) diff --git a/apps/server/tsconfig.json b/apps/server/tsconfig.json index b86bbf1f16c..19e1af25e82 100644 --- a/apps/server/tsconfig.json +++ b/apps/server/tsconfig.json @@ -1,7 +1,6 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "composite": true, "types": ["node", "bun"], "lib": ["ESNext", "esnext.disposable"] }, diff --git a/bun.lock b/bun.lock index 5124db3f234..3bd3f9c3e9f 100644 --- a/bun.lock +++ b/bun.lock @@ -172,6 +172,7 @@ "devDependencies": { "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", + "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:", }, @@ -186,6 +187,7 @@ "@effect/openapi-generator": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", + "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:", }, @@ -200,6 +202,7 @@ "@effect/openapi-generator": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", + "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:", }, @@ -298,7 +301,7 @@ "@types/node": "^24.10.13", "effect": "4.0.0-beta.73", "tsdown": "^0.20.3", - "typescript": "^5.7.3", + "typescript": "~6.0.3", "vitest": "^4.0.0", }, "packages": { @@ -1982,7 +1985,7 @@ "typesafe-path": ["typesafe-path@0.2.2", "", {}, "sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA=="], - "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], "typescript-auto-import-cache": ["typescript-auto-import-cache@0.3.6", "", { "dependencies": { "semver": "^7.3.8" } }, "sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ=="], diff --git a/package.json b/package.json index 7cdcc2c7004..ad13a0666ee 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@types/bun": "^1.3.11", "@types/node": "^24.10.13", "tsdown": "^0.20.3", - "typescript": "^5.7.3", + "typescript": "~6.0.3", "vitest": "^4.0.0" } }, diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 5b2ad2cc412..e51e4f01d5d 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -26,6 +26,7 @@ "devDependencies": { "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", + "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:" } diff --git a/packages/contracts/src/orchestration.test.ts b/packages/contracts/src/orchestration.test.ts index a9cdfd22532..a175b0b7c34 100644 --- a/packages/contracts/src/orchestration.test.ts +++ b/packages/contracts/src/orchestration.test.ts @@ -379,7 +379,9 @@ it.effect("decodes thread archived and unarchived events", () => }, }); - assert.strictEqual(archived.type, "thread.archived"); + if (archived.type !== "thread.archived") { + assert.fail(`Expected thread.archived event, received ${archived.type}.`); + } assert.strictEqual(archived.payload.archivedAt, "2026-01-01T00:00:00.000Z"); assert.strictEqual(unarchived.type, "thread.unarchived"); }), diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json index 73a306f847a..374bac55202 100644 --- a/packages/contracts/tsconfig.json +++ b/packages/contracts/tsconfig.json @@ -1,5 +1,7 @@ { "extends": "../../tsconfig.base.json", - "compilerOptions": {}, + "compilerOptions": { + "types": ["node"] + }, "include": ["src"] } diff --git a/packages/effect-acp/package.json b/packages/effect-acp/package.json index c6233cb421d..85ee9ed9233 100644 --- a/packages/effect-acp/package.json +++ b/packages/effect-acp/package.json @@ -45,6 +45,7 @@ "@effect/openapi-generator": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", + "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:" } diff --git a/packages/effect-acp/tsconfig.json b/packages/effect-acp/tsconfig.json index 04f1d37800f..8891950e04e 100644 --- a/packages/effect-acp/tsconfig.json +++ b/packages/effect-acp/tsconfig.json @@ -1,5 +1,7 @@ { "extends": "../../tsconfig.base.json", - "compilerOptions": {}, + "compilerOptions": { + "types": ["node"] + }, "include": ["src", "scripts", "test"] } diff --git a/packages/effect-codex-app-server/package.json b/packages/effect-codex-app-server/package.json index fb2df244401..7e67d3f2d07 100644 --- a/packages/effect-codex-app-server/package.json +++ b/packages/effect-codex-app-server/package.json @@ -38,6 +38,7 @@ "@effect/openapi-generator": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", + "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:" } diff --git a/packages/effect-codex-app-server/tsconfig.json b/packages/effect-codex-app-server/tsconfig.json index 04f1d37800f..8891950e04e 100644 --- a/packages/effect-codex-app-server/tsconfig.json +++ b/packages/effect-codex-app-server/tsconfig.json @@ -1,5 +1,7 @@ { "extends": "../../tsconfig.base.json", - "compilerOptions": {}, + "compilerOptions": { + "types": ["node"] + }, "include": ["src", "scripts", "test"] } diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 73a306f847a..374bac55202 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -1,5 +1,7 @@ { "extends": "../../tsconfig.base.json", - "compilerOptions": {}, + "compilerOptions": { + "types": ["node"] + }, "include": ["src"] } diff --git a/packages/ssh/tsconfig.json b/packages/ssh/tsconfig.json index 73a306f847a..374bac55202 100644 --- a/packages/ssh/tsconfig.json +++ b/packages/ssh/tsconfig.json @@ -1,5 +1,7 @@ { "extends": "../../tsconfig.base.json", - "compilerOptions": {}, + "compilerOptions": { + "types": ["node"] + }, "include": ["src"] } diff --git a/packages/tailscale/tsconfig.json b/packages/tailscale/tsconfig.json index 73a306f847a..374bac55202 100644 --- a/packages/tailscale/tsconfig.json +++ b/packages/tailscale/tsconfig.json @@ -1,5 +1,7 @@ { "extends": "../../tsconfig.base.json", - "compilerOptions": {}, + "compilerOptions": { + "types": ["node"] + }, "include": ["src"] } From b4ef2d40031454620af1b467d7691388f88c283f Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 14:42:12 -0700 Subject: [PATCH 02/10] Remove Node ambient types from contracts Co-authored-by: codex --- bun.lock | 1 - packages/contracts/package.json | 1 - packages/contracts/src/orchestration.test.ts | 3 +-- packages/contracts/tsconfig.json | 4 +--- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/bun.lock b/bun.lock index 3bd3f9c3e9f..385c507a9ae 100644 --- a/bun.lock +++ b/bun.lock @@ -172,7 +172,6 @@ "devDependencies": { "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", - "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:", }, diff --git a/packages/contracts/package.json b/packages/contracts/package.json index e51e4f01d5d..5b2ad2cc412 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -26,7 +26,6 @@ "devDependencies": { "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", - "@types/node": "catalog:", "typescript": "catalog:", "vitest": "catalog:" } diff --git a/packages/contracts/src/orchestration.test.ts b/packages/contracts/src/orchestration.test.ts index a175b0b7c34..3dc83933e38 100644 --- a/packages/contracts/src/orchestration.test.ts +++ b/packages/contracts/src/orchestration.test.ts @@ -1,5 +1,4 @@ -import assert from "node:assert/strict"; -import { it } from "@effect/vitest"; +import { assert, it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as Schema from "effect/Schema"; diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json index 374bac55202..73a306f847a 100644 --- a/packages/contracts/tsconfig.json +++ b/packages/contracts/tsconfig.json @@ -1,7 +1,5 @@ { "extends": "../../tsconfig.base.json", - "compilerOptions": { - "types": ["node"] - }, + "compilerOptions": {}, "include": ["src"] } From fd3fe08156690189b370b2c718c92570e813dc7c Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 14:44:08 -0700 Subject: [PATCH 03/10] Migrate TypeScript checks to Effect TSGo Co-authored-by: codex --- apps/desktop/package.json | 4 +- apps/desktop/src/app/DesktopAppIdentity.ts | 2 +- apps/desktop/src/app/DesktopAssets.ts | 2 +- apps/desktop/src/app/DesktopEnvironment.ts | 2 +- apps/desktop/src/app/DesktopLifecycle.ts | 7 +- apps/desktop/src/app/DesktopObservability.ts | 2 +- apps/desktop/src/app/DesktopState.ts | 2 +- .../backend/DesktopBackendConfiguration.ts | 2 +- .../src/backend/DesktopBackendManager.ts | 2 +- .../src/backend/DesktopServerExposure.ts | 4 +- apps/desktop/src/electron/ElectronApp.ts | 2 +- apps/desktop/src/electron/ElectronDialog.ts | 2 +- apps/desktop/src/electron/ElectronMenu.ts | 2 +- apps/desktop/src/electron/ElectronProtocol.ts | 2 +- .../src/electron/ElectronSafeStorage.ts | 2 +- apps/desktop/src/electron/ElectronShell.ts | 2 +- apps/desktop/src/electron/ElectronTheme.ts | 2 +- apps/desktop/src/electron/ElectronUpdater.ts | 2 +- apps/desktop/src/electron/ElectronWindow.ts | 2 +- apps/desktop/src/ipc/DesktopIpc.ts | 4 +- .../src/settings/DesktopAppSettings.ts | 2 +- .../src/settings/DesktopClientSettings.ts | 2 +- .../src/settings/DesktopSavedEnvironments.ts | 2 +- .../src/shell/DesktopShellEnvironment.ts | 2 +- apps/desktop/src/ssh/DesktopSshEnvironment.ts | 2 +- .../src/ssh/DesktopSshPasswordPrompts.ts | 2 +- apps/desktop/src/ssh/DesktopSshRemoteApi.ts | 2 +- apps/desktop/src/updates/DesktopUpdates.ts | 2 +- .../src/window/DesktopApplicationMenu.ts | 2 +- apps/desktop/src/window/DesktopWindow.ts | 2 +- apps/server/package.json | 4 +- .../auth/Layers/BootstrapCredentialService.ts | 4 +- .../auth/Layers/SessionCredentialService.ts | 4 +- .../src/auth/Services/AuthControlPlane.ts | 2 +- apps/server/src/bin.test.ts | 2 +- .../orchestration/Layers/CheckpointReactor.ts | 78 ++++++++++--------- apps/server/src/process/externalLauncher.ts | 2 +- apps/server/src/processRunner.ts | 2 +- .../Services/ProjectSetupScriptRunner.ts | 2 +- .../src/provider/Layers/ClaudeAdapter.test.ts | 2 +- .../src/provider/Layers/CodexAdapter.test.ts | 2 +- .../src/provider/Layers/CursorAdapter.test.ts | 2 +- .../src/provider/Layers/EventNdjsonLogger.ts | 29 +++---- .../provider/Layers/OpenCodeAdapter.test.ts | 2 +- .../provider/Layers/ProviderEventLoggers.ts | 2 +- apps/server/src/provider/opencodeRuntime.ts | 2 +- .../src/provider/providerMaintenanceRunner.ts | 2 +- apps/server/src/server.test.ts | 25 +++--- apps/server/src/serverRuntimeStartup.ts | 11 ++- apps/server/src/serverSettings.test.ts | 24 +++--- .../src/sourceControl/AzureDevOpsCli.ts | 2 +- apps/server/src/sourceControl/BitbucketApi.ts | 2 +- apps/server/src/sourceControl/GitHubCli.ts | 2 +- apps/server/src/sourceControl/GitLabCli.ts | 2 +- .../sourceControl/SourceControlDiscovery.ts | 2 +- .../sourceControl/SourceControlProvider.ts | 2 +- .../SourceControlProviderRegistry.ts | 2 +- .../SourceControlRepositoryService.ts | 2 +- .../src/textGeneration/TextGeneration.ts | 2 +- apps/server/src/ws.ts | 47 ++++++----- apps/web/package.json | 4 +- apps/web/src/session-logic.test.ts | 4 +- apps/web/tsconfig.json | 6 +- bun.lock | 65 +++++++++------- oxlint-plugin-t3code/package.json | 4 +- package.json | 9 ++- packages/client-runtime/package.json | 4 +- packages/contracts/package.json | 4 +- packages/effect-acp/package.json | 4 +- packages/effect-acp/src/agent.ts | 4 +- packages/effect-acp/src/client.ts | 2 +- packages/effect-codex-app-server/package.json | 4 +- .../effect-codex-app-server/src/client.ts | 2 +- packages/shared/package.json | 4 +- packages/shared/src/schemaJson.test.ts | 18 ++++- packages/shared/src/schemaJson.ts | 7 +- packages/ssh/package.json | 4 +- packages/ssh/src/auth.ts | 2 +- packages/ssh/src/tunnel.ts | 5 +- packages/tailscale/package.json | 4 +- scripts/package.json | 4 +- 81 files changed, 266 insertions(+), 237 deletions(-) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index ead57b5cbf2..2e84e4255d4 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -10,7 +10,7 @@ "dev:electron": "node scripts/dev-electron.mjs", "build": "tsdown", "start": "node scripts/start-electron.mjs", - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run --passWithNoTests", "smoke-test": "node scripts/smoke-test.mjs" }, @@ -25,11 +25,9 @@ "electron-updater": "^6.6.2" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", "tsdown": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" }, "productName": "T3 Code (Alpha)" diff --git a/apps/desktop/src/app/DesktopAppIdentity.ts b/apps/desktop/src/app/DesktopAppIdentity.ts index c525d01d9d8..7a566194ab1 100644 --- a/apps/desktop/src/app/DesktopAppIdentity.ts +++ b/apps/desktop/src/app/DesktopAppIdentity.ts @@ -26,7 +26,7 @@ export interface DesktopAppIdentityShape { export class DesktopAppIdentity extends Context.Service< DesktopAppIdentity, DesktopAppIdentityShape ->()("t3/desktop/AppIdentity") {} +>()("@t3tools/desktop/app/DesktopAppIdentity") {} const normalizeCommitHash = (value: string): Option.Option => { const trimmed = value.trim(); diff --git a/apps/desktop/src/app/DesktopAssets.ts b/apps/desktop/src/app/DesktopAssets.ts index 60ff477d34f..a9c1d62e685 100644 --- a/apps/desktop/src/app/DesktopAssets.ts +++ b/apps/desktop/src/app/DesktopAssets.ts @@ -18,7 +18,7 @@ export interface DesktopAssetsShape { } export class DesktopAssets extends Context.Service()( - "t3/desktop/Assets", + "@t3tools/desktop/app/DesktopAssets", ) {} const resolveResourcePath = Effect.fn("desktop.assets.resolveResourcePath")(function* ( diff --git a/apps/desktop/src/app/DesktopEnvironment.ts b/apps/desktop/src/app/DesktopEnvironment.ts index a5212f25358..2c5db8a16d8 100644 --- a/apps/desktop/src/app/DesktopEnvironment.ts +++ b/apps/desktop/src/app/DesktopEnvironment.ts @@ -78,7 +78,7 @@ export interface DesktopEnvironmentShape { export class DesktopEnvironment extends Context.Service< DesktopEnvironment, DesktopEnvironmentShape ->()("t3/desktop/Environment") {} +>()("@t3tools/desktop/app/DesktopEnvironment") {} const APP_BASE_NAME = "T3 Code"; diff --git a/apps/desktop/src/app/DesktopLifecycle.ts b/apps/desktop/src/app/DesktopLifecycle.ts index b9a7636a411..a7957ffca19 100644 --- a/apps/desktop/src/app/DesktopLifecycle.ts +++ b/apps/desktop/src/app/DesktopLifecycle.ts @@ -24,7 +24,7 @@ export interface DesktopShutdownShape { } export class DesktopShutdown extends Context.Service()( - "t3/desktop/Shutdown", + "@t3tools/desktop/app/DesktopLifecycle/DesktopShutdown", ) {} const makeShutdown = Effect.gen(function* () { @@ -61,8 +61,11 @@ export interface DesktopLifecycleShape { readonly register: Effect.Effect; } +/** + * @effect-expect-leaking DesktopEnvironment | DesktopShutdown | DesktopState | DesktopWindow | ElectronApp | ElectronTheme + */ export class DesktopLifecycle extends Context.Service()( - "t3/desktop/Lifecycle", + "@t3tools/desktop/app/DesktopLifecycle", ) {} const { logInfo: logLifecycleInfo, logError: logLifecycleError } = diff --git a/apps/desktop/src/app/DesktopObservability.ts b/apps/desktop/src/app/DesktopObservability.ts index 4eeb76bd62a..2349fe52dc3 100644 --- a/apps/desktop/src/app/DesktopObservability.ts +++ b/apps/desktop/src/app/DesktopObservability.ts @@ -43,7 +43,7 @@ export interface DesktopBackendOutputLogShape { export class DesktopBackendOutputLog extends Context.Service< DesktopBackendOutputLog, DesktopBackendOutputLogShape ->()("t3/desktop/BackendOutputLog") {} +>()("@t3tools/desktop/app/DesktopObservability/DesktopBackendOutputLog") {} const textEncoder = new TextEncoder(); const textDecoder = new TextDecoder(); diff --git a/apps/desktop/src/app/DesktopState.ts b/apps/desktop/src/app/DesktopState.ts index 43960ada65f..f325c99d229 100644 --- a/apps/desktop/src/app/DesktopState.ts +++ b/apps/desktop/src/app/DesktopState.ts @@ -9,7 +9,7 @@ export interface DesktopStateShape { } export class DesktopState extends Context.Service()( - "t3/desktop/State", + "@t3tools/desktop/app/DesktopState", ) {} export const layer = Layer.effect( diff --git a/apps/desktop/src/backend/DesktopBackendConfiguration.ts b/apps/desktop/src/backend/DesktopBackendConfiguration.ts index 4ce117205a6..5e4e034b5e7 100644 --- a/apps/desktop/src/backend/DesktopBackendConfiguration.ts +++ b/apps/desktop/src/backend/DesktopBackendConfiguration.ts @@ -24,7 +24,7 @@ export interface DesktopBackendConfigurationShape { export class DesktopBackendConfiguration extends Context.Service< DesktopBackendConfiguration, DesktopBackendConfigurationShape ->()("t3/desktop/BackendConfiguration") {} +>()("@t3tools/desktop/backend/DesktopBackendConfiguration") {} interface BackendObservabilitySettings { readonly otlpTracesUrl: Option.Option; diff --git a/apps/desktop/src/backend/DesktopBackendManager.ts b/apps/desktop/src/backend/DesktopBackendManager.ts index 2e3bc39b309..07693a82707 100644 --- a/apps/desktop/src/backend/DesktopBackendManager.ts +++ b/apps/desktop/src/backend/DesktopBackendManager.ts @@ -116,7 +116,7 @@ export interface DesktopBackendManagerShape { export class DesktopBackendManager extends Context.Service< DesktopBackendManager, DesktopBackendManagerShape ->()("t3/desktop/BackendManager") {} +>()("@t3tools/desktop/backend/DesktopBackendManager") {} const { logWarning: logBackendManagerWarning, logError: logBackendManagerError } = DesktopObservability.makeComponentLogger("desktop-backend-manager"); diff --git a/apps/desktop/src/backend/DesktopServerExposure.ts b/apps/desktop/src/backend/DesktopServerExposure.ts index bd0939a7775..839c76e65da 100644 --- a/apps/desktop/src/backend/DesktopServerExposure.ts +++ b/apps/desktop/src/backend/DesktopServerExposure.ts @@ -275,7 +275,7 @@ export interface DesktopServerExposureShape { export class DesktopServerExposure extends Context.Service< DesktopServerExposure, DesktopServerExposureShape ->()("t3/desktop/ServerExposure") {} +>()("@t3tools/desktop/backend/DesktopServerExposure") {} export interface DesktopNetworkInterfacesServiceShape { readonly read: Effect.Effect; @@ -284,7 +284,7 @@ export interface DesktopNetworkInterfacesServiceShape { export class DesktopNetworkInterfacesService extends Context.Service< DesktopNetworkInterfacesService, DesktopNetworkInterfacesServiceShape ->()("t3/desktop/ServerExposure/NetworkInterfaces") {} +>()("@t3tools/desktop/backend/DesktopServerExposure/DesktopNetworkInterfacesService") {} interface RuntimeState { readonly requestedMode: DesktopServerExposureMode; diff --git a/apps/desktop/src/electron/ElectronApp.ts b/apps/desktop/src/electron/ElectronApp.ts index 2e330c2d275..bd7a5ec8476 100644 --- a/apps/desktop/src/electron/ElectronApp.ts +++ b/apps/desktop/src/electron/ElectronApp.ts @@ -39,7 +39,7 @@ export interface ElectronAppShape { } export class ElectronApp extends Context.Service()( - "t3/desktop/electron/App", + "@t3tools/desktop/electron/ElectronApp", ) {} const addScopedAppListener = >( diff --git a/apps/desktop/src/electron/ElectronDialog.ts b/apps/desktop/src/electron/ElectronDialog.ts index 5a4fdfd7ac4..74e6ae58848 100644 --- a/apps/desktop/src/electron/ElectronDialog.ts +++ b/apps/desktop/src/electron/ElectronDialog.ts @@ -29,7 +29,7 @@ export interface ElectronDialogShape { } export class ElectronDialog extends Context.Service()( - "t3/desktop/electron/Dialog", + "@t3tools/desktop/electron/ElectronDialog", ) {} const make = ElectronDialog.of({ diff --git a/apps/desktop/src/electron/ElectronMenu.ts b/apps/desktop/src/electron/ElectronMenu.ts index 7164fdb54c1..66b809b2ac7 100644 --- a/apps/desktop/src/electron/ElectronMenu.ts +++ b/apps/desktop/src/electron/ElectronMenu.ts @@ -33,7 +33,7 @@ export interface ElectronMenuShape { } export class ElectronMenu extends Context.Service()( - "t3/desktop/electron/Menu", + "@t3tools/desktop/electron/ElectronMenu", ) {} function normalizeContextMenuItems(source: readonly ContextMenuItem[]): ContextMenuItem[] { diff --git a/apps/desktop/src/electron/ElectronProtocol.ts b/apps/desktop/src/electron/ElectronProtocol.ts index 32d23ba485d..a56e442ddcb 100644 --- a/apps/desktop/src/electron/ElectronProtocol.ts +++ b/apps/desktop/src/electron/ElectronProtocol.ts @@ -52,7 +52,7 @@ export interface ElectronProtocolShape { } export class ElectronProtocol extends Context.Service()( - "t3/desktop/electron/Protocol", + "@t3tools/desktop/electron/ElectronProtocol", ) {} export function normalizeDesktopProtocolPathname(rawPath: string): Option.Option { diff --git a/apps/desktop/src/electron/ElectronSafeStorage.ts b/apps/desktop/src/electron/ElectronSafeStorage.ts index eebb3e2b2f8..c7b46265887 100644 --- a/apps/desktop/src/electron/ElectronSafeStorage.ts +++ b/apps/desktop/src/electron/ElectronSafeStorage.ts @@ -48,7 +48,7 @@ export interface ElectronSafeStorageShape { export class ElectronSafeStorage extends Context.Service< ElectronSafeStorage, ElectronSafeStorageShape ->()("@t3tools/desktop/ElectronSafeStorage") {} +>()("@t3tools/desktop/electron/ElectronSafeStorage") {} const make = ElectronSafeStorage.of({ isEncryptionAvailable: Effect.try({ diff --git a/apps/desktop/src/electron/ElectronShell.ts b/apps/desktop/src/electron/ElectronShell.ts index 09826a95b09..0ecce3bf70e 100644 --- a/apps/desktop/src/electron/ElectronShell.ts +++ b/apps/desktop/src/electron/ElectronShell.ts @@ -26,7 +26,7 @@ export interface ElectronShellShape { } export class ElectronShell extends Context.Service()( - "t3/desktop/electron/Shell", + "@t3tools/desktop/electron/ElectronShell", ) {} const make = ElectronShell.of({ diff --git a/apps/desktop/src/electron/ElectronTheme.ts b/apps/desktop/src/electron/ElectronTheme.ts index ecf1f98dade..1e23d228504 100644 --- a/apps/desktop/src/electron/ElectronTheme.ts +++ b/apps/desktop/src/electron/ElectronTheme.ts @@ -13,7 +13,7 @@ export interface ElectronThemeShape { } export class ElectronTheme extends Context.Service()( - "t3/desktop/electron/Theme", + "@t3tools/desktop/electron/ElectronTheme", ) {} const make = ElectronTheme.of({ diff --git a/apps/desktop/src/electron/ElectronUpdater.ts b/apps/desktop/src/electron/ElectronUpdater.ts index ad8afbcdfc3..7f3edf02aa8 100644 --- a/apps/desktop/src/electron/ElectronUpdater.ts +++ b/apps/desktop/src/electron/ElectronUpdater.ts @@ -67,7 +67,7 @@ export interface ElectronUpdaterShape { } export class ElectronUpdater extends Context.Service()( - "t3/desktop/electron/Updater", + "@t3tools/desktop/electron/ElectronUpdater", ) {} export const layer = Layer.succeed(ElectronUpdater, { diff --git a/apps/desktop/src/electron/ElectronWindow.ts b/apps/desktop/src/electron/ElectronWindow.ts index ed31fb0700e..d41a8326e63 100644 --- a/apps/desktop/src/electron/ElectronWindow.ts +++ b/apps/desktop/src/electron/ElectronWindow.ts @@ -33,7 +33,7 @@ export interface ElectronWindowShape { } export class ElectronWindow extends Context.Service()( - "t3/desktop/electron/Window", + "@t3tools/desktop/electron/ElectronWindow", ) {} const make = Effect.gen(function* () { diff --git a/apps/desktop/src/ipc/DesktopIpc.ts b/apps/desktop/src/ipc/DesktopIpc.ts index 05a0f25512e..6d954a97aec 100644 --- a/apps/desktop/src/ipc/DesktopIpc.ts +++ b/apps/desktop/src/ipc/DesktopIpc.ts @@ -42,7 +42,9 @@ export interface DesktopIpcShape { ) => Effect.Effect; } -export class DesktopIpc extends Context.Service()("t3/desktop/Ipc") {} +export class DesktopIpc extends Context.Service()( + "@t3tools/desktop/ipc/DesktopIpc", +) {} export const make = (ipcMain: DesktopIpcMain): DesktopIpcShape => DesktopIpc.of({ diff --git a/apps/desktop/src/settings/DesktopAppSettings.ts b/apps/desktop/src/settings/DesktopAppSettings.ts index 0a5079b1057..97b590b0350 100644 --- a/apps/desktop/src/settings/DesktopAppSettings.ts +++ b/apps/desktop/src/settings/DesktopAppSettings.ts @@ -89,7 +89,7 @@ export interface DesktopAppSettingsShape { export class DesktopAppSettings extends Context.Service< DesktopAppSettings, DesktopAppSettingsShape ->()("t3/desktop/AppSettings") {} +>()("@t3tools/desktop/settings/DesktopAppSettings") {} export function resolveDefaultDesktopSettings(appVersion: string): DesktopSettings { return { diff --git a/apps/desktop/src/settings/DesktopClientSettings.ts b/apps/desktop/src/settings/DesktopClientSettings.ts index 521ea467afa..be494359412 100644 --- a/apps/desktop/src/settings/DesktopClientSettings.ts +++ b/apps/desktop/src/settings/DesktopClientSettings.ts @@ -49,7 +49,7 @@ export interface DesktopClientSettingsShape { export class DesktopClientSettings extends Context.Service< DesktopClientSettings, DesktopClientSettingsShape ->()("t3/desktop/ClientSettings") {} +>()("@t3tools/desktop/settings/DesktopClientSettings") {} const readClientSettings = ( fileSystem: FileSystem.FileSystem, diff --git a/apps/desktop/src/settings/DesktopSavedEnvironments.ts b/apps/desktop/src/settings/DesktopSavedEnvironments.ts index 77524ed7697..494e5c3253f 100644 --- a/apps/desktop/src/settings/DesktopSavedEnvironments.ts +++ b/apps/desktop/src/settings/DesktopSavedEnvironments.ts @@ -121,7 +121,7 @@ export interface DesktopSavedEnvironmentsShape { export class DesktopSavedEnvironments extends Context.Service< DesktopSavedEnvironments, DesktopSavedEnvironmentsShape ->()("t3/desktop/SavedEnvironments") {} +>()("@t3tools/desktop/settings/DesktopSavedEnvironments") {} function toPersistedSavedEnvironmentRecord( record: PersistedSavedEnvironmentStorageRecord, diff --git a/apps/desktop/src/shell/DesktopShellEnvironment.ts b/apps/desktop/src/shell/DesktopShellEnvironment.ts index 358729e05ef..f57873d9fb8 100644 --- a/apps/desktop/src/shell/DesktopShellEnvironment.ts +++ b/apps/desktop/src/shell/DesktopShellEnvironment.ts @@ -26,7 +26,7 @@ export interface DesktopShellEnvironmentShape { export class DesktopShellEnvironment extends Context.Service< DesktopShellEnvironment, DesktopShellEnvironmentShape ->()("t3/desktop/ShellEnvironment") {} +>()("@t3tools/desktop/shell/DesktopShellEnvironment") {} const LOGIN_SHELL_ENV_NAMES = [ "PATH", diff --git a/apps/desktop/src/ssh/DesktopSshEnvironment.ts b/apps/desktop/src/ssh/DesktopSshEnvironment.ts index 2fbf1f4357b..595d3bea304 100644 --- a/apps/desktop/src/ssh/DesktopSshEnvironment.ts +++ b/apps/desktop/src/ssh/DesktopSshEnvironment.ts @@ -68,7 +68,7 @@ export interface DesktopSshEnvironmentShape { export class DesktopSshEnvironment extends Context.Service< DesktopSshEnvironment, DesktopSshEnvironmentShape ->()("t3/desktop/SshEnvironment") {} +>()("@t3tools/desktop/ssh/DesktopSshEnvironment") {} export interface DesktopSshEnvironmentLayerOptions { readonly resolveCliPackageSpec?: () => string; diff --git a/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts b/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts index b3e7bd23032..1d50f9ca325 100644 --- a/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts +++ b/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts @@ -129,7 +129,7 @@ export interface DesktopSshPasswordPromptsShape { export class DesktopSshPasswordPrompts extends Context.Service< DesktopSshPasswordPrompts, DesktopSshPasswordPromptsShape ->()("t3/desktop/SshPasswordPrompts") {} +>()("@t3tools/desktop/ssh/DesktopSshPasswordPrompts") {} interface PendingSshPasswordPrompt { readonly requestId: string; diff --git a/apps/desktop/src/ssh/DesktopSshRemoteApi.ts b/apps/desktop/src/ssh/DesktopSshRemoteApi.ts index 60184d098a6..fda08491060 100644 --- a/apps/desktop/src/ssh/DesktopSshRemoteApi.ts +++ b/apps/desktop/src/ssh/DesktopSshRemoteApi.ts @@ -53,7 +53,7 @@ export interface DesktopSshRemoteApiShape { export class DesktopSshRemoteApi extends Context.Service< DesktopSshRemoteApi, DesktopSshRemoteApiShape ->()("t3/desktop/SshRemoteApi") {} +>()("@t3tools/desktop/ssh/DesktopSshRemoteApi") {} const decodeExecutionEnvironmentDescriptor = Schema.decodeUnknownEffect( ExecutionEnvironmentDescriptor, diff --git a/apps/desktop/src/updates/DesktopUpdates.ts b/apps/desktop/src/updates/DesktopUpdates.ts index 8c0acd2e8a6..056bca4a0e1 100644 --- a/apps/desktop/src/updates/DesktopUpdates.ts +++ b/apps/desktop/src/updates/DesktopUpdates.ts @@ -100,7 +100,7 @@ export interface DesktopUpdatesShape { } export class DesktopUpdates extends Context.Service()( - "t3/desktop/Updates", + "@t3tools/desktop/updates/DesktopUpdates", ) {} const { diff --git a/apps/desktop/src/window/DesktopApplicationMenu.ts b/apps/desktop/src/window/DesktopApplicationMenu.ts index 5e65d81910a..2d41fa9db86 100644 --- a/apps/desktop/src/window/DesktopApplicationMenu.ts +++ b/apps/desktop/src/window/DesktopApplicationMenu.ts @@ -21,7 +21,7 @@ export interface DesktopApplicationMenuShape { export class DesktopApplicationMenu extends Context.Service< DesktopApplicationMenu, DesktopApplicationMenuShape ->()("t3/desktop/ApplicationMenu") {} +>()("@t3tools/desktop/window/DesktopApplicationMenu") {} type DesktopApplicationMenuRuntimeServices = | DesktopUpdates.DesktopUpdates diff --git a/apps/desktop/src/window/DesktopWindow.ts b/apps/desktop/src/window/DesktopWindow.ts index 8ebd1041c6b..e88c52d42ec 100644 --- a/apps/desktop/src/window/DesktopWindow.ts +++ b/apps/desktop/src/window/DesktopWindow.ts @@ -62,7 +62,7 @@ export interface DesktopWindowShape { } export class DesktopWindow extends Context.Service()( - "t3/desktop/Window", + "@t3tools/desktop/window/DesktopWindow", ) {} const { logInfo: logWindowInfo, logWarning: logWindowWarning } = diff --git a/apps/server/package.json b/apps/server/package.json index 5d99a91dbc3..fac1b924c2b 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -19,7 +19,7 @@ "build": "node scripts/cli.ts build", "build:bundle": "tsdown", "start": "node dist/bin.mjs", - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run" }, "dependencies": { @@ -34,7 +34,6 @@ "node-pty": "^1.1.0" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@t3tools/contracts": "workspace:*", "@t3tools/shared": "workspace:*", @@ -45,7 +44,6 @@ "effect-acp": "workspace:*", "effect-codex-app-server": "workspace:*", "tsdown": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" }, "engines": { diff --git a/apps/server/src/auth/Layers/BootstrapCredentialService.ts b/apps/server/src/auth/Layers/BootstrapCredentialService.ts index 77d865eca68..394a20dc62f 100644 --- a/apps/server/src/auth/Layers/BootstrapCredentialService.ts +++ b/apps/server/src/auth/Layers/BootstrapCredentialService.ts @@ -1,4 +1,5 @@ import type { AuthPairingLink } from "@t3tools/contracts"; +import * as Crypto from "effect/Crypto"; import * as DateTime from "effect/DateTime"; import * as Duration from "effect/Duration"; import * as Effect from "effect/Effect"; @@ -46,6 +47,7 @@ const generatePairingToken = (): string => { }; export const makeBootstrapCredentialService = Effect.gen(function* () { + const crypto = yield* Crypto.Crypto; const config = yield* ServerConfig; const pairingLinks = yield* AuthPairingLinkRepository; const seededGrantsRef = yield* Ref.make(new Map()); @@ -141,7 +143,7 @@ export const makeBootstrapCredentialService = Effect.gen(function* () { const issueOneTimeToken: BootstrapCredentialServiceShape["issueOneTimeToken"] = (input) => Effect.gen(function* () { - const id = crypto.randomUUID(); + const id = yield* crypto.randomUUIDv4; const credential = generatePairingToken(); const ttl = input?.ttl ?? DEFAULT_ONE_TIME_TOKEN_TTL_MINUTES; const now = yield* DateTime.now; diff --git a/apps/server/src/auth/Layers/SessionCredentialService.ts b/apps/server/src/auth/Layers/SessionCredentialService.ts index 31e2b13240a..7d06c40da8d 100644 --- a/apps/server/src/auth/Layers/SessionCredentialService.ts +++ b/apps/server/src/auth/Layers/SessionCredentialService.ts @@ -1,5 +1,6 @@ import { AuthSessionId, type AuthClientMetadata, type AuthClientSession } from "@t3tools/contracts"; import * as Clock from "effect/Clock"; +import * as Crypto from "effect/Crypto"; import * as DateTime from "effect/DateTime"; import * as Duration from "effect/Duration"; import * as Effect from "effect/Effect"; @@ -90,6 +91,7 @@ function toAuthClientSession(input: Omit): AuthCli } export const makeSessionCredentialService = Effect.gen(function* () { + const crypto = yield* Crypto.Crypto; const serverConfig = yield* ServerConfig; const secretStore = yield* ServerSecretStore; const authSessions = yield* AuthSessionRepository; @@ -203,7 +205,7 @@ export const makeSessionCredentialService = Effect.gen(function* () { const encodeClaims = Schema.encodeEffect(Schema.fromJsonString(SessionClaims)); const issue: SessionCredentialServiceShape["issue"] = (input) => Effect.gen(function* () { - const sessionId = AuthSessionId.make(crypto.randomUUID()); + const sessionId = AuthSessionId.make(yield* crypto.randomUUIDv4); const issuedAt = yield* DateTime.now; const expiresAt = DateTime.add(issuedAt, { milliseconds: Duration.toMillis(input?.ttl ?? DEFAULT_SESSION_TTL), diff --git a/apps/server/src/auth/Services/AuthControlPlane.ts b/apps/server/src/auth/Services/AuthControlPlane.ts index b5e67639a65..f71c6e32e9b 100644 --- a/apps/server/src/auth/Services/AuthControlPlane.ts +++ b/apps/server/src/auth/Services/AuthControlPlane.ts @@ -69,5 +69,5 @@ export interface AuthControlPlaneShape { } export class AuthControlPlane extends Context.Service()( - "t3/AuthControlPlane", + "t3/auth/Services/AuthControlPlane", ) {} diff --git a/apps/server/src/bin.test.ts b/apps/server/src/bin.test.ts index a7bf2686101..fbf6d80c560 100644 --- a/apps/server/src/bin.test.ts +++ b/apps/server/src/bin.test.ts @@ -1,4 +1,4 @@ -// @effect-diagnostics-next-line nodeBuiltinImport:off - NodeHttpServer.layer takes `NodeHttp.createServer` as arg +// @effect-diagnostics nodeBuiltinImport:off - CLI integration exercises Node HTTP and filesystem boundaries. import * as NodeHttp from "node:http"; import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; diff --git a/apps/server/src/orchestration/Layers/CheckpointReactor.ts b/apps/server/src/orchestration/Layers/CheckpointReactor.ts index da135b0c056..1fbd74d1ad9 100644 --- a/apps/server/src/orchestration/Layers/CheckpointReactor.ts +++ b/apps/server/src/orchestration/Layers/CheckpointReactor.ts @@ -9,6 +9,7 @@ import { type ProviderRuntimeEvent, } from "@t3tools/contracts"; import * as Cause from "effect/Cause"; +import * as Crypto from "effect/Crypto"; import * as DateTime from "effect/DateTime"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; @@ -69,10 +70,11 @@ function checkpointStatusFromRuntime(status: string | undefined): "ready" | "mis } } -const serverCommandId = (tag: string): CommandId => - CommandId.make(`server:${tag}:${crypto.randomUUID()}`); - const make = Effect.gen(function* () { + const crypto = yield* Crypto.Crypto; + const randomUUID = crypto.randomUUIDv4.pipe(Effect.orDie); + const serverCommandId = (tag: string) => + randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`))); const orchestrationEngine = yield* OrchestrationEngineService; const projectionSnapshotQuery = yield* ProjectionSnapshotQuery; const providerService = yield* ProviderService; @@ -87,23 +89,25 @@ const make = Effect.gen(function* () { readonly detail: string; readonly createdAt: string; }) => - orchestrationEngine.dispatch({ - type: "thread.activity.append", - commandId: serverCommandId("checkpoint-revert-failure"), - threadId: input.threadId, - activity: { - id: EventId.make(crypto.randomUUID()), - tone: "error", - kind: "checkpoint.revert.failed", - summary: "Checkpoint revert failed", - payload: { - turnCount: input.turnCount, - detail: input.detail, + Effect.gen(function* () { + yield* orchestrationEngine.dispatch({ + type: "thread.activity.append", + commandId: yield* serverCommandId("checkpoint-revert-failure"), + threadId: input.threadId, + activity: { + id: EventId.make(yield* randomUUID), + tone: "error", + kind: "checkpoint.revert.failed", + summary: "Checkpoint revert failed", + payload: { + turnCount: input.turnCount, + detail: input.detail, + }, + turnId: null, + createdAt: input.createdAt, }, - turnId: null, createdAt: input.createdAt, - }, - createdAt: input.createdAt, + }); }); const appendCaptureFailureActivity = (input: { @@ -112,22 +116,24 @@ const make = Effect.gen(function* () { readonly detail: string; readonly createdAt: string; }) => - orchestrationEngine.dispatch({ - type: "thread.activity.append", - commandId: serverCommandId("checkpoint-capture-failure"), - threadId: input.threadId, - activity: { - id: EventId.make(crypto.randomUUID()), - tone: "error", - kind: "checkpoint.capture.failed", - summary: "Checkpoint capture failed", - payload: { - detail: input.detail, + Effect.gen(function* () { + yield* orchestrationEngine.dispatch({ + type: "thread.activity.append", + commandId: yield* serverCommandId("checkpoint-capture-failure"), + threadId: input.threadId, + activity: { + id: EventId.make(yield* randomUUID), + tone: "error", + kind: "checkpoint.capture.failed", + summary: "Checkpoint capture failed", + payload: { + detail: input.detail, + }, + turnId: input.turnId, + createdAt: input.createdAt, }, - turnId: input.turnId, createdAt: input.createdAt, - }, - createdAt: input.createdAt, + }); }); const resolveSessionRuntimeForThread = Effect.fn("resolveSessionRuntimeForThread")(function* ( @@ -281,7 +287,7 @@ const make = Effect.gen(function* () { yield* orchestrationEngine.dispatch({ type: "thread.turn.diff.complete", - commandId: serverCommandId("checkpoint-turn-diff-complete"), + commandId: yield* serverCommandId("checkpoint-turn-diff-complete"), threadId: input.threadId, turnId: input.turnId, completedAt: input.createdAt, @@ -311,10 +317,10 @@ const make = Effect.gen(function* () { yield* orchestrationEngine.dispatch({ type: "thread.activity.append", - commandId: serverCommandId("checkpoint-captured-activity"), + commandId: yield* serverCommandId("checkpoint-captured-activity"), threadId: input.threadId, activity: { - id: EventId.make(crypto.randomUUID()), + id: EventId.make(yield* randomUUID), tone: "info", kind: "checkpoint.captured", summary: "Checkpoint captured", @@ -697,7 +703,7 @@ const make = Effect.gen(function* () { yield* orchestrationEngine .dispatch({ type: "thread.revert.complete", - commandId: serverCommandId("checkpoint-revert-complete"), + commandId: yield* serverCommandId("checkpoint-revert-complete"), threadId: event.payload.threadId, turnCount: event.payload.turnCount, createdAt: now, diff --git a/apps/server/src/process/externalLauncher.ts b/apps/server/src/process/externalLauncher.ts index cbfee1d7054..da19864dcf8 100644 --- a/apps/server/src/process/externalLauncher.ts +++ b/apps/server/src/process/externalLauncher.ts @@ -257,7 +257,7 @@ export interface ExternalLauncherShape { * ExternalLauncher - Service tag for browser/editor launch operations. */ export class ExternalLauncher extends Context.Service()( - "t3/process/ExternalLauncher", + "t3/process/externalLauncher", ) {} // ============================== diff --git a/apps/server/src/processRunner.ts b/apps/server/src/processRunner.ts index 55988a8533a..45135bf9d2a 100644 --- a/apps/server/src/processRunner.ts +++ b/apps/server/src/processRunner.ts @@ -90,7 +90,7 @@ export interface ProcessRunnerShape { } export class ProcessRunner extends Context.Service()( - "t3/process/ProcessRunner", + "t3/processRunner", ) {} const DEFAULT_TIMEOUT = "60 seconds"; diff --git a/apps/server/src/project/Services/ProjectSetupScriptRunner.ts b/apps/server/src/project/Services/ProjectSetupScriptRunner.ts index 184c75b5019..17168eda7f1 100644 --- a/apps/server/src/project/Services/ProjectSetupScriptRunner.ts +++ b/apps/server/src/project/Services/ProjectSetupScriptRunner.ts @@ -41,4 +41,4 @@ export interface ProjectSetupScriptRunnerShape { export class ProjectSetupScriptRunner extends Context.Service< ProjectSetupScriptRunner, ProjectSetupScriptRunnerShape ->()("t3/project/ProjectSetupScriptRunner") {} +>()("t3/project/Services/ProjectSetupScriptRunner") {} diff --git a/apps/server/src/provider/Layers/ClaudeAdapter.test.ts b/apps/server/src/provider/Layers/ClaudeAdapter.test.ts index 19ed1811760..aad1654ecd9 100644 --- a/apps/server/src/provider/Layers/ClaudeAdapter.test.ts +++ b/apps/server/src/provider/Layers/ClaudeAdapter.test.ts @@ -42,7 +42,7 @@ const decodeClaudeSettings = Schema.decodeSync(ClaudeSettings); // Test-local service tag so the rest of the file can keep using `yield* ClaudeAdapter`. class ClaudeAdapter extends Context.Service()( - "test/ClaudeAdapter", + "t3/provider/Layers/ClaudeAdapter.test/ClaudeAdapter", ) {} class FakeClaudeQuery implements AsyncIterable { diff --git a/apps/server/src/provider/Layers/CodexAdapter.test.ts b/apps/server/src/provider/Layers/CodexAdapter.test.ts index c5eaa536c3f..3ae98ec248c 100644 --- a/apps/server/src/provider/Layers/CodexAdapter.test.ts +++ b/apps/server/src/provider/Layers/CodexAdapter.test.ts @@ -50,7 +50,7 @@ const decodeCodexSettings = Schema.decodeSync(CodexSettings); // Test-local service tag so the rest of the file can keep using `yield* CodexAdapter`. class CodexAdapter extends Context.Service()( - "test/CodexAdapter", + "t3/provider/Layers/CodexAdapter.test/CodexAdapter", ) {} const asThreadId = (value: string): ThreadId => ThreadId.make(value); diff --git a/apps/server/src/provider/Layers/CursorAdapter.test.ts b/apps/server/src/provider/Layers/CursorAdapter.test.ts index 43644fd6f49..0c54c92b6dd 100644 --- a/apps/server/src/provider/Layers/CursorAdapter.test.ts +++ b/apps/server/src/provider/Layers/CursorAdapter.test.ts @@ -32,7 +32,7 @@ const decodeCursorSettings = Schema.decodeSync(CursorSettings); // Test-local service tag so the rest of the file can keep using `yield* CursorAdapter`. class CursorAdapter extends Context.Service()( - "test/CursorAdapter", + "t3/provider/Layers/CursorAdapter.test/CursorAdapter", ) {} const __dirname = path.dirname(fileURLToPath(import.meta.url)); diff --git a/apps/server/src/provider/Layers/EventNdjsonLogger.ts b/apps/server/src/provider/Layers/EventNdjsonLogger.ts index 3b36cc20c90..04377ad520c 100644 --- a/apps/server/src/provider/Layers/EventNdjsonLogger.ts +++ b/apps/server/src/provider/Layers/EventNdjsonLogger.ts @@ -14,6 +14,7 @@ import { RotatingFileSink } from "@t3tools/shared/logging"; import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; import * as Logger from "effect/Logger"; +import * as Schema from "effect/Schema"; import * as Scope from "effect/Scope"; import * as SynchronizedRef from "effect/SynchronizedRef"; @@ -24,6 +25,7 @@ const DEFAULT_MAX_FILES = 10; const DEFAULT_BATCH_WINDOW_MS = 200; const GLOBAL_THREAD_SEGMENT = "_global"; const LOG_SCOPE = "provider-observability"; +const encodeUnknownJsonString = Schema.encodeUnknownEffect(Schema.UnknownFromJsonString); export type EventNdjsonStream = "native" | "canonical" | "orchestration"; @@ -87,26 +89,13 @@ function resolveStreamLabel(stream: EventNdjsonStream): string { const toLogMessage = Effect.fn("toLogMessage")(function* ( event: unknown, ): Effect.fn.Return { - const serialized = yield* Effect.sync(() => { - try { - return { ok: true as const, value: JSON.stringify(event) }; - } catch (error) { - return { ok: false as const, error }; - } - }); - - if (!serialized.ok) { - yield* logWarning("failed to serialize provider event log record", { - error: serialized.error, - }); - return undefined; - } - - if (typeof serialized.value !== "string") { - return undefined; - } - - return serialized.value; + return yield* encodeUnknownJsonString(event).pipe( + Effect.catch((error) => + logWarning("failed to serialize provider event log record", { error }).pipe( + Effect.as(undefined), + ), + ), + ); }); const makeThreadWriter = Effect.fn("makeThreadWriter")(function* (input: { diff --git a/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts b/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts index 66dc5edc671..4849272035c 100644 --- a/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts +++ b/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts @@ -37,7 +37,7 @@ import { // Test-local service tag so the rest of the file can keep using `yield* OpenCodeAdapter`. class OpenCodeAdapter extends Context.Service()( - "test/OpenCodeAdapter", + "t3/provider/Layers/OpenCodeAdapter.test/OpenCodeAdapter", ) {} const asThreadId = (value: string): ThreadId => ThreadId.make(value); diff --git a/apps/server/src/provider/Layers/ProviderEventLoggers.ts b/apps/server/src/provider/Layers/ProviderEventLoggers.ts index 14e9a1075d5..711aa6e76b6 100644 --- a/apps/server/src/provider/Layers/ProviderEventLoggers.ts +++ b/apps/server/src/provider/Layers/ProviderEventLoggers.ts @@ -50,7 +50,7 @@ export interface ProviderEventLoggersShape { export class ProviderEventLoggers extends Context.Service< ProviderEventLoggers, ProviderEventLoggersShape ->()("t3/provider/ProviderEventLoggers") {} +>()("t3/provider/Layers/ProviderEventLoggers") {} /** * Constant value used by tests / boot layers that want to opt out of native diff --git a/apps/server/src/provider/opencodeRuntime.ts b/apps/server/src/provider/opencodeRuntime.ts index ddeb9f26431..9c48e441032 100644 --- a/apps/server/src/provider/opencodeRuntime.ts +++ b/apps/server/src/provider/opencodeRuntime.ts @@ -544,7 +544,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { }); export class OpenCodeRuntime extends Context.Service()( - "t3/provider/OpenCodeRuntime", + "t3/provider/opencodeRuntime", ) {} export const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe( diff --git a/apps/server/src/provider/providerMaintenanceRunner.ts b/apps/server/src/provider/providerMaintenanceRunner.ts index 5f76afb34d3..6a759b79f7d 100644 --- a/apps/server/src/provider/providerMaintenanceRunner.ts +++ b/apps/server/src/provider/providerMaintenanceRunner.ts @@ -53,7 +53,7 @@ export interface ProviderMaintenanceRunnerShape { export class ProviderMaintenanceRunner extends Context.Service< ProviderMaintenanceRunner, ProviderMaintenanceRunnerShape ->()("t3/provider/ProviderMaintenanceRunner") {} +>()("t3/provider/providerMaintenanceRunner") {} class ProviderMaintenanceCommandError extends Data.TaggedError("ProviderMaintenanceCommandError")<{ readonly message: string; diff --git a/apps/server/src/server.test.ts b/apps/server/src/server.test.ts index 3ae2885f024..48f3ffeb995 100644 --- a/apps/server/src/server.test.ts +++ b/apps/server/src/server.test.ts @@ -37,6 +37,7 @@ import * as Layer from "effect/Layer"; import * as ManagedRuntime from "effect/ManagedRuntime"; import * as Option from "effect/Option"; import * as Path from "effect/Path"; +import * as Schema from "effect/Schema"; import * as Stream from "effect/Stream"; import { ChildProcessSpawner } from "effect/unstable/process"; import { @@ -52,6 +53,7 @@ import * as Socket from "effect/unstable/socket/Socket"; import { vi } from "vitest"; const TEST_EPOCH = DateTime.makeUnsafe("1970-01-01T00:00:00.000Z"); +const encodeJsonRequestBody = Schema.encodeUnknownEffect(Schema.UnknownFromJsonString); import type { ServerConfigShape } from "./config.ts"; import { deriveServerPaths, ServerConfig } from "./config.ts"; @@ -795,6 +797,7 @@ const bootstrapBrowserSession = ( ) => Effect.gen(function* () { const bootstrapUrl = yield* getHttpServerUrl("/api/auth/bootstrap"); + const requestBody = yield* encodeJsonRequestBody({ credential }); const response = yield* Effect.promise(() => fetch(bootstrapUrl, { method: "POST", @@ -802,9 +805,7 @@ const bootstrapBrowserSession = ( "content-type": "application/json", ...options?.headers, }, - body: JSON.stringify({ - credential, - }), + body: requestBody, }), ); const body = (yield* Effect.promise(() => response.json())) as { @@ -827,6 +828,7 @@ const bootstrapBearerSession = ( ) => Effect.gen(function* () { const bootstrapUrl = yield* getHttpServerUrl("/api/auth/bootstrap/bearer"); + const requestBody = yield* encodeJsonRequestBody({ credential }); const response = yield* Effect.promise(() => fetch(bootstrapUrl, { method: "POST", @@ -834,9 +836,7 @@ const bootstrapBearerSession = ( "content-type": "application/json", ...options?.headers, }, - body: JSON.stringify({ - credential, - }), + body: requestBody, }), ); const body = (yield* Effect.promise(() => response.json())) as { @@ -1358,6 +1358,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { }>; const revokeUrl = yield* getHttpServerUrl("/api/auth/pairing-links/revoke"); + const revokeBody = yield* encodeJsonRequestBody({ id: createdBody.id }); const revokeResponse = yield* Effect.promise(() => fetch(revokeUrl, { method: "POST", @@ -1365,7 +1366,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { cookie: ownerCookie, "content-type": "application/json", }, - body: JSON.stringify({ id: createdBody.id }), + body: revokeBody, }), ); const revokedBootstrap = yield* bootstrapBrowserSession(createdBody.credential); @@ -1421,6 +1422,9 @@ it.layer(NodeServices.layer)("server router seam", (it) => { const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); const pairingTokenUrl = yield* getHttpServerUrl("/api/auth/pairing-token"); + const ownerPairingBodyInput = yield* encodeJsonRequestBody({ + label: "Julius iPhone", + }); const ownerPairingResponse = yield* Effect.promise(() => fetch(pairingTokenUrl, { method: "POST", @@ -1428,9 +1432,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { cookie: ownerCookie, "content-type": "application/json", }, - body: JSON.stringify({ - label: "Julius iPhone", - }), + body: ownerPairingBodyInput, }), ); const ownerPairingBody = (yield* Effect.promise(() => ownerPairingResponse.json())) as { @@ -1556,6 +1558,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.isDefined(pairedSessionId); const revokeUrl = yield* getHttpServerUrl("/api/auth/clients/revoke"); + const revokeBody = yield* encodeJsonRequestBody({ sessionId: pairedSessionId }); const revokeResponse = yield* Effect.promise(() => fetch(revokeUrl, { method: "POST", @@ -1563,7 +1566,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { cookie: ownerCookie, "content-type": "application/json", }, - body: JSON.stringify({ sessionId: pairedSessionId }), + body: revokeBody, }), ); const pairedClientPairingResponse = yield* HttpClient.post("/api/auth/pairing-token", { diff --git a/apps/server/src/serverRuntimeStartup.ts b/apps/server/src/serverRuntimeStartup.ts index 9ec536105c8..a6215fa6fc9 100644 --- a/apps/server/src/serverRuntimeStartup.ts +++ b/apps/server/src/serverRuntimeStartup.ts @@ -19,6 +19,7 @@ import * as Ref from "effect/Ref"; import * as Scope from "effect/Scope"; import * as Context from "effect/Context"; import * as Console from "effect/Console"; +import * as Crypto from "effect/Crypto"; import * as DateTime from "effect/DateTime"; import { ServerConfig } from "./config.ts"; @@ -170,6 +171,8 @@ export const resolveWelcomeBase = Effect.gen(function* () { }); export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () { + const crypto = yield* Crypto.Crypto; + const randomUUID = crypto.randomUUIDv4.pipe(Effect.orDie); const serverConfig = yield* ServerConfig; const projectionReadModelQuery = yield* ProjectionSnapshotQuery; const orchestrationEngine = yield* OrchestrationEngineService; @@ -188,12 +191,12 @@ export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () { if (Option.isNone(existingProject)) { const createdAt = DateTime.formatIso(yield* DateTime.now); - nextProjectId = ProjectId.make(crypto.randomUUID()); + nextProjectId = ProjectId.make(yield* randomUUID); const bootstrapProjectTitle = path.basename(serverConfig.cwd) || "project"; nextProjectDefaultModelSelection = getAutoBootstrapDefaultModelSelection(); yield* orchestrationEngine.dispatch({ type: "project.create", - commandId: CommandId.make(crypto.randomUUID()), + commandId: CommandId.make(yield* randomUUID), projectId: nextProjectId, title: bootstrapProjectTitle, workspaceRoot: serverConfig.cwd, @@ -210,10 +213,10 @@ export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () { yield* projectionReadModelQuery.getFirstActiveThreadIdByProjectId(nextProjectId); if (Option.isNone(existingThreadId)) { const createdAt = DateTime.formatIso(yield* DateTime.now); - const createdThreadId = ThreadId.make(crypto.randomUUID()); + const createdThreadId = ThreadId.make(yield* randomUUID); yield* orchestrationEngine.dispatch({ type: "thread.create", - commandId: CommandId.make(crypto.randomUUID()), + commandId: CommandId.make(yield* randomUUID), threadId: createdThreadId, projectId: nextProjectId, title: "New thread", diff --git a/apps/server/src/serverSettings.test.ts b/apps/server/src/serverSettings.test.ts index 7af27f0b7cf..d24f2ee2826 100644 --- a/apps/server/src/serverSettings.test.ts +++ b/apps/server/src/serverSettings.test.ts @@ -16,6 +16,9 @@ import * as Schema from "effect/Schema"; import { ServerConfig } from "./config.ts"; import { ServerSettingsLive, ServerSettingsService } from "./serverSettings.ts"; +const decodeSettingsPatch = Schema.decodeUnknownEffect(ServerSettingsPatch); +const decodeServerSettings = Schema.decodeUnknownEffect(ServerSettings); + const makeServerSettingsLayer = () => ServerSettingsLive.pipe( Layer.provideMerge( @@ -29,15 +32,16 @@ const makeServerSettingsLayer = () => it.layer(NodeServices.layer)("server settings", (it) => { it.effect("decodes nested settings patches", () => - Effect.sync(() => { - const decodePatch = Schema.decodeUnknownSync(ServerSettingsPatch); - - assert.deepEqual(decodePatch({ providers: { codex: { binaryPath: "/tmp/codex" } } }), { - providers: { codex: { binaryPath: "/tmp/codex" } }, - }); + Effect.gen(function* () { + assert.deepEqual( + yield* decodeSettingsPatch({ providers: { codex: { binaryPath: "/tmp/codex" } } }), + { + providers: { codex: { binaryPath: "/tmp/codex" } }, + }, + ); assert.deepEqual( - decodePatch({ + yield* decodeSettingsPatch({ textGenerationModelSelection: { options: [{ id: "fastMode", value: false }], }, @@ -54,10 +58,8 @@ it.layer(NodeServices.layer)("server settings", (it) => { it.effect( "decodes legacy object-shaped textGenerationModelSelection.options from settings.json", () => - Effect.sync(() => { - const decode = Schema.decodeUnknownSync(ServerSettings); - - const decoded = decode({ + Effect.gen(function* () { + const decoded = yield* decodeServerSettings({ textGenerationModelSelection: { provider: ProviderDriverKind.make("codex"), model: "gpt-5.4-mini", diff --git a/apps/server/src/sourceControl/AzureDevOpsCli.ts b/apps/server/src/sourceControl/AzureDevOpsCli.ts index d4a4d69267b..29a57f993c4 100644 --- a/apps/server/src/sourceControl/AzureDevOpsCli.ts +++ b/apps/server/src/sourceControl/AzureDevOpsCli.ts @@ -94,7 +94,7 @@ export interface AzureDevOpsCliShape { } export class AzureDevOpsCli extends Context.Service()( - "t3/source-control/AzureDevOpsCli", + "t3/sourceControl/AzureDevOpsCli", ) {} function errorText(error: VcsError | unknown): string { diff --git a/apps/server/src/sourceControl/BitbucketApi.ts b/apps/server/src/sourceControl/BitbucketApi.ts index 748113ba04f..3bcba65fe0f 100644 --- a/apps/server/src/sourceControl/BitbucketApi.ts +++ b/apps/server/src/sourceControl/BitbucketApi.ts @@ -154,7 +154,7 @@ export interface BitbucketApiShape { } export class BitbucketApi extends Context.Service()( - "t3/source-control/BitbucketApi", + "t3/sourceControl/BitbucketApi", ) {} function nonEmpty(value: string | undefined): Option.Option { diff --git a/apps/server/src/sourceControl/GitHubCli.ts b/apps/server/src/sourceControl/GitHubCli.ts index 14d01aab2ed..77393b75c1c 100644 --- a/apps/server/src/sourceControl/GitHubCli.ts +++ b/apps/server/src/sourceControl/GitHubCli.ts @@ -93,7 +93,7 @@ export interface GitHubCliShape { } export class GitHubCli extends Context.Service()( - "t3/source-control/GitHubCli", + "t3/sourceControl/GitHubCli", ) {} function errorText(error: VcsError | unknown): string { diff --git a/apps/server/src/sourceControl/GitLabCli.ts b/apps/server/src/sourceControl/GitLabCli.ts index faabe87263d..789e0cf72e3 100644 --- a/apps/server/src/sourceControl/GitLabCli.ts +++ b/apps/server/src/sourceControl/GitLabCli.ts @@ -97,7 +97,7 @@ export interface GitLabCliShape { } export class GitLabCli extends Context.Service()( - "t3/source-control/GitLabCli", + "t3/sourceControl/GitLabCli", ) {} function isVcsProcessSpawnError(error: unknown): boolean { diff --git a/apps/server/src/sourceControl/SourceControlDiscovery.ts b/apps/server/src/sourceControl/SourceControlDiscovery.ts index 6b00cf779fa..eab46d23560 100644 --- a/apps/server/src/sourceControl/SourceControlDiscovery.ts +++ b/apps/server/src/sourceControl/SourceControlDiscovery.ts @@ -64,7 +64,7 @@ export interface SourceControlDiscoveryShape { export class SourceControlDiscovery extends Context.Service< SourceControlDiscovery, SourceControlDiscoveryShape ->()("t3/source-control/SourceControlDiscovery") {} +>()("t3/sourceControl/SourceControlDiscovery") {} export const layer = Layer.effect( SourceControlDiscovery, diff --git a/apps/server/src/sourceControl/SourceControlProvider.ts b/apps/server/src/sourceControl/SourceControlProvider.ts index a0465008212..f0602f03d14 100644 --- a/apps/server/src/sourceControl/SourceControlProvider.ts +++ b/apps/server/src/sourceControl/SourceControlProvider.ts @@ -99,4 +99,4 @@ export interface SourceControlProviderShape { export class SourceControlProvider extends Context.Service< SourceControlProvider, SourceControlProviderShape ->()("t3/source-control/SourceControlProvider") {} +>()("t3/sourceControl/SourceControlProvider") {} diff --git a/apps/server/src/sourceControl/SourceControlProviderRegistry.ts b/apps/server/src/sourceControl/SourceControlProviderRegistry.ts index 28826e764b0..5b625e6690b 100644 --- a/apps/server/src/sourceControl/SourceControlProviderRegistry.ts +++ b/apps/server/src/sourceControl/SourceControlProviderRegistry.ts @@ -51,7 +51,7 @@ export interface SourceControlProviderRegistryShape { export class SourceControlProviderRegistry extends Context.Service< SourceControlProviderRegistry, SourceControlProviderRegistryShape ->()("t3/source-control/SourceControlProviderRegistry") {} +>()("t3/sourceControl/SourceControlProviderRegistry") {} function unsupportedProvider( kind: SourceControlProviderKind, diff --git a/apps/server/src/sourceControl/SourceControlRepositoryService.ts b/apps/server/src/sourceControl/SourceControlRepositoryService.ts index f1ee1940390..3f8c146f4c7 100644 --- a/apps/server/src/sourceControl/SourceControlRepositoryService.ts +++ b/apps/server/src/sourceControl/SourceControlRepositoryService.ts @@ -39,7 +39,7 @@ export interface SourceControlRepositoryServiceShape { export class SourceControlRepositoryService extends Context.Service< SourceControlRepositoryService, SourceControlRepositoryServiceShape ->()("t3/source-control/SourceControlRepositoryService") {} +>()("t3/sourceControl/SourceControlRepositoryService") {} function detailFromUnknown(cause: unknown): string { if (typeof cause === "object" && cause !== null) { diff --git a/apps/server/src/textGeneration/TextGeneration.ts b/apps/server/src/textGeneration/TextGeneration.ts index 36a23d509db..2b149dabbb8 100644 --- a/apps/server/src/textGeneration/TextGeneration.ts +++ b/apps/server/src/textGeneration/TextGeneration.ts @@ -116,7 +116,7 @@ export interface TextGenerationShape { * TextGeneration - Service tag for commit and PR text generation. */ export class TextGeneration extends Context.Service()( - "t3/text-generation/TextGeneration", + "t3/textGeneration/TextGeneration", ) {} type TextGenerationOp = diff --git a/apps/server/src/ws.ts b/apps/server/src/ws.ts index e99672161c9..e5d8be8706b 100644 --- a/apps/server/src/ws.ts +++ b/apps/server/src/ws.ts @@ -1,4 +1,5 @@ import * as Cause from "effect/Cause"; +import * as Crypto from "effect/Crypto"; import * as DateTime from "effect/DateTime"; import * as Duration from "effect/Duration"; import * as Effect from "effect/Effect"; @@ -160,6 +161,8 @@ function toAuthAccessStreamEvent( const makeWsRpcLayer = (currentSessionId: AuthSessionId) => WsRpcGroup.toLayer( Effect.gen(function* () { + const crypto = yield* Crypto.Crypto; + const randomUUID = crypto.randomUUIDv4.pipe(Effect.orDie); const projectionSnapshotQuery = yield* ProjectionSnapshotQuery; const orchestrationEngine = yield* OrchestrationEngineService; const checkpointDiffQuery = yield* CheckpointDiffQuery; @@ -196,7 +199,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => const processDiagnostics = yield* ProcessDiagnostics.ProcessDiagnostics; const processResourceMonitor = yield* ProcessResourceMonitor.ProcessResourceMonitor; const serverCommandId = (tag: string) => - CommandId.make(`server:${tag}:${crypto.randomUUID()}`); + randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`))); const loadAuthAccessSnapshot = () => Effect.all({ @@ -212,20 +215,22 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => readonly payload: Record; readonly tone: "info" | "error"; }) => - orchestrationEngine.dispatch({ - type: "thread.activity.append", - commandId: serverCommandId("setup-script-activity"), - threadId: input.threadId, - activity: { - id: EventId.make(crypto.randomUUID()), - tone: input.tone, - kind: input.kind, - summary: input.summary, - payload: input.payload, - turnId: null, + Effect.gen(function* () { + yield* orchestrationEngine.dispatch({ + type: "thread.activity.append", + commandId: yield* serverCommandId("setup-script-activity"), + threadId: input.threadId, + activity: { + id: EventId.make(yield* randomUUID), + tone: input.tone, + kind: input.kind, + summary: input.summary, + payload: input.payload, + turnId: null, + createdAt: input.createdAt, + }, createdAt: input.createdAt, - }, - createdAt: input.createdAt, + }); }); const toDispatchCommandError = (cause: unknown, fallbackMessage: string) => @@ -370,13 +375,13 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => const cleanupCreatedThread = () => createdThread - ? orchestrationEngine - .dispatch({ + ? Effect.gen(function* () { + yield* orchestrationEngine.dispatch({ type: "thread.delete", - commandId: serverCommandId("bootstrap-thread-delete"), + commandId: yield* serverCommandId("bootstrap-thread-delete"), threadId: command.threadId, - }) - .pipe(Effect.ignoreCause({ log: true })) + }); + }).pipe(Effect.ignoreCause({ log: true })) : Effect.void; const recordSetupScriptLaunchFailure = (input: { @@ -499,7 +504,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => if (bootstrap?.createThread) { yield* orchestrationEngine.dispatch({ type: "thread.create", - commandId: serverCommandId("bootstrap-thread-create"), + commandId: yield* serverCommandId("bootstrap-thread-create"), threadId: command.threadId, projectId: bootstrap.createThread.projectId, title: bootstrap.createThread.title, @@ -523,7 +528,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => targetWorktreePath = worktree.worktree.path; yield* orchestrationEngine.dispatch({ type: "thread.meta.update", - commandId: serverCommandId("bootstrap-thread-meta-update"), + commandId: yield* serverCommandId("bootstrap-thread-meta-update"), threadId: command.threadId, branch: worktree.worktree.refName, worktreePath: targetWorktreePath, diff --git a/apps/web/package.json b/apps/web/package.json index 03f77c3aba8..9ef17991e64 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -7,7 +7,7 @@ "dev": "vite", "build": "vite build", "preview": "vite preview", - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run --passWithNoTests", "test:browser": "vitest run --config vitest.browser.config.ts", "test:browser:install": "playwright install --with-deps chromium" @@ -43,7 +43,6 @@ "zustand": "^5.0.11" }, "devDependencies": { - "@effect/language-service": "catalog:", "@rolldown/plugin-babel": "^0.2.0", "@tailwindcss/vite": "^4.0.0", "@tanstack/router-plugin": "^1.161.0", @@ -57,7 +56,6 @@ "msw": "2.12.11", "playwright": "^1.58.2", "tailwindcss": "^4.0.0", - "typescript": "catalog:", "vite": "^8.0.0", "vitest": "catalog:", "vitest-browser-react": "^2.0.5" diff --git a/apps/web/src/session-logic.test.ts b/apps/web/src/session-logic.test.ts index baf384d6af2..c36a4942992 100644 --- a/apps/web/src/session-logic.test.ts +++ b/apps/web/src/session-logic.test.ts @@ -22,6 +22,8 @@ import { isLatestTurnSettled, } from "./session-logic"; +let nextActivityId = 0; + function makeActivity(overrides: { id?: string; createdAt?: string; @@ -34,7 +36,7 @@ function makeActivity(overrides: { }): OrchestrationThreadActivity { const payload = overrides.payload ?? {}; return { - id: EventId.make(overrides.id ?? crypto.randomUUID()), + id: EventId.make(overrides.id ?? `activity-${nextActivityId++}`), createdAt: overrides.createdAt ?? "2026-02-23T00:00:00.000Z", kind: overrides.kind ?? "tool.started", summary: overrides.summary ?? "Tool call", diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 0a23203c7b0..8d6954ae0f0 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -30,7 +30,11 @@ "unknownInEffectCatch": "error", "strictBooleanExpressions": "off", "preferSchemaOverJson": "error", - "schemaSyncInEffect": "error" + "schemaSyncInEffect": "error", + "globalDate": "off", + "globalConsole": "off", + "globalRandom": "off", + "globalTimers": "off" } } ] diff --git a/bun.lock b/bun.lock index 385c507a9ae..2695cd8916d 100644 --- a/bun.lock +++ b/bun.lock @@ -5,13 +5,13 @@ "": { "name": "@t3tools/monorepo", "devDependencies": { - "@effect/language-service": "catalog:", + "@effect/tsgo": "catalog:", "@oxlint/plugins": "^1.63.0", "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", "oxfmt": "^0.40.0", "oxlint": "^1.63.0", "turbo": "^2.3.3", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -29,11 +29,9 @@ "electron-updater": "^6.6.2", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", "tsdown": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -66,7 +64,6 @@ "node-pty": "^1.1.0", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@t3tools/contracts": "workspace:*", "@t3tools/shared": "workspace:*", @@ -77,7 +74,6 @@ "effect-acp": "workspace:*", "effect-codex-app-server": "workspace:*", "tsdown": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -115,7 +111,6 @@ "zustand": "^5.0.11", }, "devDependencies": { - "@effect/language-service": "catalog:", "@rolldown/plugin-babel": "^0.2.0", "@tailwindcss/vite": "^4.0.0", "@tanstack/router-plugin": "^1.161.0", @@ -129,7 +124,6 @@ "msw": "2.12.11", "playwright": "^1.58.2", "tailwindcss": "^4.0.0", - "typescript": "catalog:", "vite": "^8.0.0", "vitest": "catalog:", "vitest-browser-react": "^2.0.5", @@ -143,10 +137,8 @@ "effect": "catalog:", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@types/bun": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -158,8 +150,6 @@ "effect": "catalog:", }, "devDependencies": { - "@effect/language-service": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -170,9 +160,7 @@ "effect": "catalog:", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -182,12 +170,10 @@ "effect": "catalog:", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/openapi-generator": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -197,12 +183,10 @@ "effect": "catalog:", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/openapi-generator": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -213,11 +197,9 @@ "effect": "catalog:", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -229,11 +211,9 @@ "effect": "catalog:", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -244,10 +224,8 @@ "effect": "catalog:", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -261,10 +239,8 @@ "effect": "catalog:", }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@types/bun": "catalog:", - "typescript": "catalog:", "vitest": "catalog:", }, }, @@ -288,16 +264,17 @@ }, "catalog": { "@effect/atom-react": "4.0.0-beta.73", - "@effect/language-service": "0.84.2", "@effect/openapi-generator": "4.0.0-beta.73", "@effect/platform-bun": "4.0.0-beta.73", "@effect/platform-node": "4.0.0-beta.73", "@effect/platform-node-shared": "4.0.0-beta.73", "@effect/sql-sqlite-bun": "4.0.0-beta.73", + "@effect/tsgo": "0.11.4", "@effect/vitest": "4.0.0-beta.73", "@pierre/diffs": "1.1.20", "@types/bun": "^1.3.11", "@types/node": "^24.10.13", + "@typescript/native-preview": "7.0.0-dev.20260421.2", "effect": "4.0.0-beta.73", "tsdown": "^0.20.3", "typescript": "~6.0.3", @@ -404,8 +381,6 @@ "@effect/atom-react": ["@effect/atom-react@4.0.0-beta.73", "", { "peerDependencies": { "effect": "^4.0.0-beta.73", "react": "^19.2.4", "scheduler": "*" } }, "sha512-RjNqEMV3z3iEFRBtJ1RVuxBNFMYxhDo2iRwck3kBYjrBuXWrKIRyqnunWJdL2KX97Gqp0orxaujG7qnIA5aIEA=="], - "@effect/language-service": ["@effect/language-service@0.84.2", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-l04qNxpiA8rY5yXWckRPJ7Mk5MNerXuNymSFf+IdflfI5i8jgL1bpBNLuP6ijg7wgjdHc/KmTnCj2kT0SCntuA=="], - "@effect/openapi-generator": ["@effect/openapi-generator@4.0.0-beta.73", "", { "peerDependencies": { "@effect/platform-node": "^4.0.0-beta.73", "effect": "^4.0.0-beta.73" }, "bin": { "openapigen": "dist/bin.js" } }, "sha512-tN1mKreMo6kypkuPy8Jt3eGoI0DberzD2/5XxEh17lTdyLg7/SUZv3LssRxtzO5+uIYzLNIHfT2zESz7gjCnwA=="], "@effect/platform-bun": ["@effect/platform-bun@4.0.0-beta.73", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.73" }, "peerDependencies": { "effect": "^4.0.0-beta.73" } }, "sha512-AQcE89eEVp0xA3SafaswiHPfo6V2YPg7T6PQbQqYK4/S2Sia5cadCm/6y7pfRmuOd4jkWI6VMbNtEDkM0NOBpw=="], @@ -416,6 +391,22 @@ "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.73", "", { "peerDependencies": { "effect": "^4.0.0-beta.73" } }, "sha512-dkTDDeBLjaKo7h1IE049Oj2BDKQOT+Kc57KbBVaSk36dRdsEmVspRMP7OGbZj3etJU3lL1GJi1BIfnb4N3uMRw=="], + "@effect/tsgo": ["@effect/tsgo@0.11.4", "", { "optionalDependencies": { "@effect/tsgo-darwin-arm64": "0.11.4", "@effect/tsgo-darwin-x64": "0.11.4", "@effect/tsgo-linux-arm": "0.11.4", "@effect/tsgo-linux-arm64": "0.11.4", "@effect/tsgo-linux-x64": "0.11.4", "@effect/tsgo-win32-arm64": "0.11.4", "@effect/tsgo-win32-x64": "0.11.4" }, "bin": { "effect-tsgo": "dist/effect-tsgo.js" } }, "sha512-wliq5Dis2gLoIUKoCRT3Iv5kpO+fKrUBJPPxIsHADeirk9HMQevKvYaBpGS3Khw1tNLmoQWsSX559owJAdHgBA=="], + + "@effect/tsgo-darwin-arm64": ["@effect/tsgo-darwin-arm64@0.11.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rslT4W8tWY8pdd48kDpY7Q+yo0xkrmcEySG1+sJfb06w7TwbywjHsGlC0BmcUaQt0qmLY+BApbWWDfZw7fgwjw=="], + + "@effect/tsgo-darwin-x64": ["@effect/tsgo-darwin-x64@0.11.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-p3v3j+zp7L7yx5ctjvA1W85I4WjOpbOcga8kUu5MFEKfYfsApxUHXwsunCVbUKwrpXqcTc0sw9AjnCNs6i6GRw=="], + + "@effect/tsgo-linux-arm": ["@effect/tsgo-linux-arm@0.11.4", "", { "os": "linux", "cpu": "arm" }, "sha512-uXsw+IbO+ltn/fbhOWWqXK8ZW3Qa5EZD+wnGbF3gIGWINthbF+/7X+CgRzvcgLBWeBfV6F83hAmOaEZ4hQmd+w=="], + + "@effect/tsgo-linux-arm64": ["@effect/tsgo-linux-arm64@0.11.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-dz5ZIQUnRzN9mpVcELYCmVERpmstes5rVHbKUb7DOWCbrbupT3tV1LCzOaNX9sIsoBKmpvdGvAWEPLHgymSgTQ=="], + + "@effect/tsgo-linux-x64": ["@effect/tsgo-linux-x64@0.11.4", "", { "os": "linux", "cpu": "x64" }, "sha512-P3m7Y4FJtziL13Muffyb99AnQeTRvo0/knfYRqoHKNwYUaNM59RO3qFi5y57Hasgd8rKat0xTPmUkK6koZPPFQ=="], + + "@effect/tsgo-win32-arm64": ["@effect/tsgo-win32-arm64@0.11.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-FKLm9Y+luZSdLpfkbdw8VXa8xy0zR+Asg078qemqHHGwRQLDVGjvIk7tj1HxBM6VQN+TwsofDd225ht83kMk8w=="], + + "@effect/tsgo-win32-x64": ["@effect/tsgo-win32-x64@0.11.4", "", { "os": "win32", "cpu": "x64" }, "sha512-oc4Y8TbLlv0b1deAILAEep1N6pnSS1d4pk7gJJM4NDXrTKWDyEulO6tXwRQ6vWkO2lhLTUVWHDFfzmMJj3HxPQ=="], + "@effect/vitest": ["@effect/vitest@4.0.0-beta.73", "", { "peerDependencies": { "effect": "^4.0.0-beta.73", "vitest": "^3.0.0 || ^4.0.0" } }, "sha512-HIZa0aekh0ak1YfzCv8GTN75Vbvxp8g+W+z9KczvtUT+LvitX3i9nhLWZLKRrUP1LaJFLPJS2UG9ZGXjxgbjBg=="], "@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="], @@ -936,6 +927,22 @@ "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="], + "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260421.2", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260421.2", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260421.2", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260421.2", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260421.2", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260421.2", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260421.2", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260421.2" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-CmajHI25HpVWE9R1XFoxr+cphJPxoYD3eFioQtAvXYkMFKnLdICMS9pXre9Pybizb75ejRxjKD5/CVG055rEIg=="], + + "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260421.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-fHv1r3ZmVo6zxuAIFmuX3w9QxbcauoG0SsWhmDwm6VmRubLlOJIcmTtlmV3JAb9oOnq8LuzZljzT7Q39fSMQDw=="], + + "@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260421.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-KWTR6xbW9t+JS7D5DQIzo75pqVXVWUxF9PMv/+S6xsnOjCVd6g0ixHcFpFMJMKSUQpGPr8Z5f7b8ks6LHW01jg=="], + + "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260421.2", "", { "os": "linux", "cpu": "arm" }, "sha512-BWLQO3nemLDSV5PoE5GPHe1dU9Dth77Kv8/cle9Ujcp4LhPo0KincdPqFH/qKeU/xvW25mgFueflZ1nc4rKuww=="], + + "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260421.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-VLMEuml3BhUb+jaL0TXQ4xvVODxJF+RhkI+tBWvlynsJI4khTXEiwWh+wPOJrsfBRYFRMXEu28Odl/HXkYze8w=="], + + "@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260421.2", "", { "os": "linux", "cpu": "x64" }, "sha512-qUrJWTB5/wv4wnRG0TRXElAxc2kykNiRNyEIEqBbLmzDlrcvAW7RRy8MXoY1ZyTiKGMu14itZ3x9oW6+blFpRw=="], + + "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260421.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Rc6NsWlZmCs5YUKVzKgwoBOoRUGsPzct4BDMRX0csD1devLBBc4AbUXWKsJRbpwIAnqMO1ld4sNHEb+wXgfNHQ=="], + + "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260421.2", "", { "os": "win32", "cpu": "x64" }, "sha512-GQv1+dya1t6EqF2Cpsb+xoozovdX10JUSf6Kl/8xNkTapzmlHd+uMr+8ku3jIASTxoRGn0Mklgjj3MDKrOTuLg=="], + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], "@vercel/config": ["@vercel/config@0.3.0", "", { "dependencies": { "@vercel/routing-utils": "6.2.0", "pretty-cache-header": "^1.0.0", "zod": "^3.22.0" }, "bin": { "config": "dist/cli.js" } }, "sha512-Tf5k5y2F478oTiQcU5R8Ntix1UejE6NdduZnI7aa1XXxjCtifX1XdRS/D2uTjiQAwIL3pLa1LSAN80ABbba+TQ=="], diff --git a/oxlint-plugin-t3code/package.json b/oxlint-plugin-t3code/package.json index 2601e70248f..97525096cca 100644 --- a/oxlint-plugin-t3code/package.json +++ b/oxlint-plugin-t3code/package.json @@ -3,7 +3,7 @@ "private": true, "type": "module", "scripts": { - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run" }, "dependencies": { @@ -12,10 +12,8 @@ "effect": "catalog:" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@types/bun": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" } } diff --git a/package.json b/package.json index ad13a0666ee..8235cbca100 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,11 @@ "@effect/platform-node-shared": "4.0.0-beta.73", "@effect/sql-sqlite-bun": "4.0.0-beta.73", "@effect/vitest": "4.0.0-beta.73", - "@effect/language-service": "0.84.2", + "@effect/tsgo": "0.11.4", "@pierre/diffs": "1.1.20", "@types/bun": "^1.3.11", "@types/node": "^24.10.13", + "@typescript/native-preview": "7.0.0-dev.20260421.2", "tsdown": "^0.20.3", "typescript": "~6.0.3", "vitest": "^4.0.0" @@ -28,7 +29,7 @@ }, "type": "module", "scripts": { - "prepare": "effect-language-service patch", + "prepare": "effect-tsgo patch", "dev": "node scripts/dev-runner.ts dev", "dev:server": "node scripts/dev-runner.ts dev:server", "dev:web": "node scripts/dev-runner.ts dev:web", @@ -61,13 +62,13 @@ "sync:vscode-icons": "node scripts/sync-vscode-icons.mjs" }, "devDependencies": { - "@effect/language-service": "catalog:", + "@effect/tsgo": "catalog:", "@oxlint/plugins": "^1.63.0", "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", "oxfmt": "^0.40.0", "oxlint": "^1.63.0", "turbo": "^2.3.3", - "typescript": "catalog:", "vitest": "catalog:" }, "overrides": { diff --git a/packages/client-runtime/package.json b/packages/client-runtime/package.json index 58bc576a24f..e3fc1fa720a 100644 --- a/packages/client-runtime/package.json +++ b/packages/client-runtime/package.json @@ -9,7 +9,7 @@ } }, "scripts": { - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run" }, "dependencies": { @@ -18,8 +18,6 @@ "effect": "catalog:" }, "devDependencies": { - "@effect/language-service": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" } } diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 5b2ad2cc412..5305b778e96 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -17,16 +17,14 @@ } }, "scripts": { - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run" }, "dependencies": { "effect": "catalog:" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" } } diff --git a/packages/effect-acp/package.json b/packages/effect-acp/package.json index 85ee9ed9233..12c7a9521a3 100644 --- a/packages/effect-acp/package.json +++ b/packages/effect-acp/package.json @@ -33,7 +33,7 @@ } }, "scripts": { - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run", "generate": "bun run scripts/generate.ts" }, @@ -41,12 +41,10 @@ "effect": "catalog:" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/openapi-generator": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" } } diff --git a/packages/effect-acp/src/agent.ts b/packages/effect-acp/src/agent.ts index 0de2b49b843..67bcd0f4c6d 100644 --- a/packages/effect-acp/src/agent.ts +++ b/packages/effect-acp/src/agent.ts @@ -207,7 +207,9 @@ export interface AcpAgentShape { ) => Effect.Effect; } -export class AcpAgent extends Context.Service()("effect-acp/AcpAgent") {} +export class AcpAgent extends Context.Service()( + "effect-acp/agent/AcpAgent", +) {} interface AcpCoreAgentRequestHandlers { initialize?: ( diff --git a/packages/effect-acp/src/client.ts b/packages/effect-acp/src/client.ts index 3052726edef..c3a59c798c7 100644 --- a/packages/effect-acp/src/client.ts +++ b/packages/effect-acp/src/client.ts @@ -263,7 +263,7 @@ export interface AcpClientShape { } export class AcpClient extends Context.Service()( - "effect-acp/AcpClient", + "effect-acp/client/AcpClient", ) {} interface AcpCoreRequestHandlers { diff --git a/packages/effect-codex-app-server/package.json b/packages/effect-codex-app-server/package.json index 7e67d3f2d07..c920f25f643 100644 --- a/packages/effect-codex-app-server/package.json +++ b/packages/effect-codex-app-server/package.json @@ -25,7 +25,7 @@ } }, "scripts": { - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run", "generate": "bun run scripts/generate.ts", "probe": "bun run test/examples/codex-app-server-probe.ts" @@ -34,12 +34,10 @@ "effect": "catalog:" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/openapi-generator": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" } } diff --git a/packages/effect-codex-app-server/src/client.ts b/packages/effect-codex-app-server/src/client.ts index 18a9ed9316c..7d409fce773 100644 --- a/packages/effect-codex-app-server/src/client.ts +++ b/packages/effect-codex-app-server/src/client.ts @@ -75,7 +75,7 @@ export interface CodexAppServerClientShape { export class CodexAppServerClient extends Context.Service< CodexAppServerClient, CodexAppServerClientShape ->()("effect-codex-app-server/CodexAppServerClient") {} +>()("effect-codex-app-server/client/CodexAppServerClient") {} type ServerRequestHandler = ( payload: unknown, diff --git a/packages/shared/package.json b/packages/shared/package.json index c27a95ea904..ad8d0646e76 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -93,7 +93,7 @@ } }, "scripts": { - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run" }, "dependencies": { @@ -101,11 +101,9 @@ "effect": "catalog:" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" } } diff --git a/packages/shared/src/schemaJson.test.ts b/packages/shared/src/schemaJson.test.ts index 7f3db7034b5..1874c0d9b03 100644 --- a/packages/shared/src/schemaJson.test.ts +++ b/packages/shared/src/schemaJson.test.ts @@ -1,6 +1,9 @@ +import * as Schema from "effect/Schema"; import { describe, expect, it } from "vitest"; -import { extractJsonObject } from "./schemaJson.ts"; +import { extractJsonObject, fromLenientJson } from "./schemaJson.ts"; + +const decodeLenientJson = Schema.decodeUnknownSync(fromLenientJson(Schema.Unknown)); describe("schemaJson helpers", () => { it("extracts a balanced JSON object from surrounding text", () => { @@ -28,4 +31,17 @@ Done.`), it("returns trimmed input when no JSON object starts", () => { expect(extractJsonObject(" no structured output ")).toBe("no structured output"); }); + + it("decodes JSON with comments and trailing commas", () => { + expect( + decodeLenientJson(`{ + // Comments are valid in settings files. + "enabled": true, + "values": [1, 2,], + }`), + ).toEqual({ + enabled: true, + values: [1, 2], + }); + }); }); diff --git a/packages/shared/src/schemaJson.ts b/packages/shared/src/schemaJson.ts index 0d879913ebf..f2deb891401 100644 --- a/packages/shared/src/schemaJson.ts +++ b/packages/shared/src/schemaJson.ts @@ -45,9 +45,10 @@ export const formatSchemaError = (cause: Cause.Cause) => { * A `Getter` that parses a lenient JSON string (tolerating trailing commas * and JS-style comments) into an unknown value. * - * Mirrors `SchemaGetter.parseJson()` but uses `parseLenientJson` instead - * of `JSON.parse`. + * Mirrors `SchemaGetter.parseJson()` but strips JSONC syntax before parsing. */ +const decodeUnknownJsonString = Schema.decodeUnknownSync(Schema.UnknownFromJsonString); + const parseLenientJsonGetter = SchemaGetter.onSome((input: string) => Effect.try({ try: () => { @@ -66,7 +67,7 @@ const parseLenientJsonGetter = SchemaGetter.onSome((input: string) => // Strip trailing commas before `}` or `]`. stripped = stripped.replace(/,(\s*[}\]])/g, "$1"); - return Option.some(JSON.parse(stripped)); + return Option.some(decodeUnknownJsonString(stripped)); }, catch: (e) => new SchemaIssue.InvalidValue(Option.some(input), { message: String(e) }), }), diff --git a/packages/ssh/package.json b/packages/ssh/package.json index a3df6fea2b4..e9ca7532516 100644 --- a/packages/ssh/package.json +++ b/packages/ssh/package.json @@ -25,7 +25,7 @@ } }, "scripts": { - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run" }, "dependencies": { @@ -34,11 +34,9 @@ "effect": "catalog:" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/platform-node": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" } } diff --git a/packages/ssh/src/auth.ts b/packages/ssh/src/auth.ts index 13ddee9ca2d..f11512cbb75 100644 --- a/packages/ssh/src/auth.ts +++ b/packages/ssh/src/auth.ts @@ -39,7 +39,7 @@ export interface SshPasswordPromptShape { } export class SshPasswordPrompt extends Context.Service()( - "@t3tools/ssh/SshPasswordPrompt", + "@t3tools/ssh/auth/SshPasswordPrompt", ) { static readonly disabledLayer = Layer.succeed( SshPasswordPrompt, diff --git a/packages/ssh/src/tunnel.ts b/packages/ssh/src/tunnel.ts index 5ee5c684779..0de48b5721d 100644 --- a/packages/ssh/src/tunnel.ts +++ b/packages/ssh/src/tunnel.ts @@ -1753,10 +1753,13 @@ const makeSshEnvironmentManager = Effect.fn("ssh/tunnel.SshEnvironmentManager.ma return SshEnvironmentManager.of({ ensureEnvironment, disconnectEnvironment }); }); +/** + * @effect-expect-leaking ChildProcessSpawner | FileSystem | HttpClient | NetService | Path | SshPasswordPrompt + */ export class SshEnvironmentManager extends Context.Service< SshEnvironmentManager, SshEnvironmentManagerShape ->()("@t3tools/ssh/SshEnvironmentManager") { +>()("@t3tools/ssh/tunnel/SshEnvironmentManager") { static readonly layer = (options: SshEnvironmentManagerOptions = {}) => Layer.effect(SshEnvironmentManager, makeSshEnvironmentManager(options)); } diff --git a/packages/tailscale/package.json b/packages/tailscale/package.json index 85fdde36e79..4109505a4e7 100644 --- a/packages/tailscale/package.json +++ b/packages/tailscale/package.json @@ -9,7 +9,7 @@ } }, "scripts": { - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run" }, "dependencies": { @@ -17,10 +17,8 @@ "effect": "catalog:" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@types/node": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" } } diff --git a/scripts/package.json b/scripts/package.json index dd801521387..d5d825714e9 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -3,7 +3,7 @@ "private": true, "type": "module", "scripts": { - "typecheck": "tsc --noEmit", + "typecheck": "tsgo --noEmit", "test": "vitest run" }, "dependencies": { @@ -14,10 +14,8 @@ "effect": "catalog:" }, "devDependencies": { - "@effect/language-service": "catalog:", "@effect/vitest": "catalog:", "@types/bun": "catalog:", - "typescript": "catalog:", "vitest": "catalog:" } } From 31734ea7cb3a97afe0962493613cc9d8baa9093c Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 14:53:02 -0700 Subject: [PATCH 04/10] Preserve typed UUID failures in TSGo migration Update native preview to 7.0.0-dev.20260527.2 and replace UUID-only generator wrappers with Effect combinators. Co-authored-by: codex --- .../orchestration/Layers/CheckpointReactor.ts | 90 +++++++++++-------- apps/server/src/serverRuntimeStartup.test.ts | 53 +++++++++++ apps/server/src/serverRuntimeStartup.ts | 2 +- apps/server/src/ws.ts | 76 +++++++++------- bun.lock | 18 ++-- package.json | 2 +- 6 files changed, 161 insertions(+), 80 deletions(-) diff --git a/apps/server/src/orchestration/Layers/CheckpointReactor.ts b/apps/server/src/orchestration/Layers/CheckpointReactor.ts index 1fbd74d1ad9..f95d5190bb0 100644 --- a/apps/server/src/orchestration/Layers/CheckpointReactor.ts +++ b/apps/server/src/orchestration/Layers/CheckpointReactor.ts @@ -14,6 +14,7 @@ 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 type * as PlatformError from "effect/PlatformError"; import * as Stream from "effect/Stream"; import { makeDrainableWorker } from "@t3tools/shared/DrainableWorker"; @@ -72,7 +73,8 @@ function checkpointStatusFromRuntime(status: string | undefined): "ready" | "mis const make = Effect.gen(function* () { const crypto = yield* Crypto.Crypto; - const randomUUID = crypto.randomUUIDv4.pipe(Effect.orDie); + const randomUUID = crypto.randomUUIDv4; + const serverEventId = randomUUID.pipe(Effect.map(EventId.make)); const serverCommandId = (tag: string) => randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`))); const orchestrationEngine = yield* OrchestrationEngineService; @@ -89,26 +91,31 @@ const make = Effect.gen(function* () { readonly detail: string; readonly createdAt: string; }) => - Effect.gen(function* () { - yield* orchestrationEngine.dispatch({ - type: "thread.activity.append", - commandId: yield* serverCommandId("checkpoint-revert-failure"), - threadId: input.threadId, - activity: { - id: EventId.make(yield* randomUUID), - tone: "error", - kind: "checkpoint.revert.failed", - summary: "Checkpoint revert failed", - payload: { - turnCount: input.turnCount, - detail: input.detail, + Effect.all({ + commandId: serverCommandId("checkpoint-revert-failure"), + activityId: serverEventId, + }).pipe( + Effect.flatMap(({ commandId, activityId }) => + orchestrationEngine.dispatch({ + type: "thread.activity.append", + commandId, + threadId: input.threadId, + activity: { + id: activityId, + tone: "error", + kind: "checkpoint.revert.failed", + summary: "Checkpoint revert failed", + payload: { + turnCount: input.turnCount, + detail: input.detail, + }, + turnId: null, + createdAt: input.createdAt, }, - turnId: null, createdAt: input.createdAt, - }, - createdAt: input.createdAt, - }); - }); + }), + ), + ); const appendCaptureFailureActivity = (input: { readonly threadId: ThreadId; @@ -116,25 +123,30 @@ const make = Effect.gen(function* () { readonly detail: string; readonly createdAt: string; }) => - Effect.gen(function* () { - yield* orchestrationEngine.dispatch({ - type: "thread.activity.append", - commandId: yield* serverCommandId("checkpoint-capture-failure"), - threadId: input.threadId, - activity: { - id: EventId.make(yield* randomUUID), - tone: "error", - kind: "checkpoint.capture.failed", - summary: "Checkpoint capture failed", - payload: { - detail: input.detail, + Effect.all({ + commandId: serverCommandId("checkpoint-capture-failure"), + activityId: serverEventId, + }).pipe( + Effect.flatMap(({ commandId, activityId }) => + orchestrationEngine.dispatch({ + type: "thread.activity.append", + commandId, + threadId: input.threadId, + activity: { + id: activityId, + tone: "error", + kind: "checkpoint.capture.failed", + summary: "Checkpoint capture failed", + payload: { + detail: input.detail, + }, + turnId: input.turnId, + createdAt: input.createdAt, }, - turnId: input.turnId, createdAt: input.createdAt, - }, - createdAt: input.createdAt, - }); - }); + }), + ), + ); const resolveSessionRuntimeForThread = Effect.fn("resolveSessionRuntimeForThread")(function* ( threadId: ThreadId, @@ -793,7 +805,11 @@ const make = Effect.gen(function* () { const processInput = ( input: ReactorInput, - ): Effect.Effect => + ): Effect.Effect< + void, + CheckpointStoreError | OrchestrationDispatchError | PlatformError.PlatformError, + never + > => input.source === "domain" ? processDomainEvent(input.event) : processRuntimeEvent(input.event); const processInputSafely = (input: ReactorInput) => diff --git a/apps/server/src/serverRuntimeStartup.test.ts b/apps/server/src/serverRuntimeStartup.test.ts index 33b9abcb98a..90eebe33820 100644 --- a/apps/server/src/serverRuntimeStartup.test.ts +++ b/apps/server/src/serverRuntimeStartup.test.ts @@ -1,10 +1,12 @@ import * as NodeServices from "@effect/platform-node/NodeServices"; import { DEFAULT_MODEL, ProjectId, ProviderInstanceId, ThreadId } from "@t3tools/contracts"; import { assert, it } from "@effect/vitest"; +import * as Crypto from "effect/Crypto"; import * as Deferred from "effect/Deferred"; import * as Effect from "effect/Effect"; import * as Fiber from "effect/Fiber"; import * as Option from "effect/Option"; +import * as PlatformError from "effect/PlatformError"; import * as Ref from "effect/Ref"; import * as Stream from "effect/Stream"; @@ -222,3 +224,54 @@ it.effect("resolveAutoBootstrapWelcomeTargets creates a project and thread when assert.deepStrictEqual(yield* Ref.get(dispatchCalls), ["project.create", "thread.create"]); }), ); + +it.effect("resolveAutoBootstrapWelcomeTargets preserves typed UUID generation failures", () => + Effect.gen(function* () { + const crypto = yield* Crypto.Crypto; + const uuidError = PlatformError.systemError({ + _tag: "Unknown", + module: "Crypto", + method: "randomUUIDv4", + description: "UUID generation unavailable", + }); + const dispatchCalls = yield* Ref.make>([]); + + const error = yield* resolveAutoBootstrapWelcomeTargets.pipe( + Effect.provideService(ServerConfig, { + cwd: "/tmp/startup-project", + autoBootstrapProjectFromCwd: true, + } as never), + Effect.provideService(ProjectionSnapshotQuery, { + getCommandReadModel: () => Effect.die("unused"), + getSnapshot: () => Effect.die("unused"), + getShellSnapshot: () => Effect.die("unused"), + getArchivedShellSnapshot: () => Effect.die("unused"), + getSnapshotSequence: () => Effect.die("unused"), + getCounts: () => Effect.die("unused"), + getActiveProjectByWorkspaceRoot: () => Effect.succeed(Option.none()), + getProjectShellById: () => Effect.die("unused"), + getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.none()), + getThreadCheckpointContext: () => Effect.succeed(Option.none()), + getFullThreadDiffContext: () => Effect.succeed(Option.none()), + getThreadShellById: () => Effect.die("unused"), + getThreadDetailById: () => Effect.die("unused"), + }), + Effect.provideService(OrchestrationEngineService, { + readEvents: () => Stream.empty, + dispatch: (command) => + Ref.update(dispatchCalls, (calls) => [...calls, command.type]).pipe( + Effect.as({ sequence: 1 }), + ), + streamDomainEvents: Stream.empty, + } satisfies OrchestrationEngineShape), + Effect.provideService(Crypto.Crypto, { + ...crypto, + randomUUIDv4: Effect.fail(uuidError), + }), + Effect.flip, + ); + + assert.strictEqual(error, uuidError); + assert.deepStrictEqual(yield* Ref.get(dispatchCalls), []); + }).pipe(Effect.provide(NodeServices.layer)), +); diff --git a/apps/server/src/serverRuntimeStartup.ts b/apps/server/src/serverRuntimeStartup.ts index a6215fa6fc9..c069623ca8f 100644 --- a/apps/server/src/serverRuntimeStartup.ts +++ b/apps/server/src/serverRuntimeStartup.ts @@ -172,7 +172,7 @@ export const resolveWelcomeBase = Effect.gen(function* () { export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () { const crypto = yield* Crypto.Crypto; - const randomUUID = crypto.randomUUIDv4.pipe(Effect.orDie); + const randomUUID = crypto.randomUUIDv4; const serverConfig = yield* ServerConfig; const projectionReadModelQuery = yield* ProjectionSnapshotQuery; const orchestrationEngine = yield* OrchestrationEngineService; diff --git a/apps/server/src/ws.ts b/apps/server/src/ws.ts index e5d8be8706b..d2dfa172826 100644 --- a/apps/server/src/ws.ts +++ b/apps/server/src/ws.ts @@ -162,7 +162,6 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => WsRpcGroup.toLayer( Effect.gen(function* () { const crypto = yield* Crypto.Crypto; - const randomUUID = crypto.randomUUIDv4.pipe(Effect.orDie); const projectionSnapshotQuery = yield* ProjectionSnapshotQuery; const orchestrationEngine = yield* OrchestrationEngineService; const checkpointDiffQuery = yield* CheckpointDiffQuery; @@ -198,6 +197,19 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => const sessions = yield* SessionCredentialService; const processDiagnostics = yield* ProcessDiagnostics.ProcessDiagnostics; const processResourceMonitor = yield* ProcessResourceMonitor.ProcessResourceMonitor; + const toDispatchCommandError = (cause: unknown, fallbackMessage: string) => + isOrchestrationDispatchCommandError(cause) + ? cause + : new OrchestrationDispatchCommandError({ + message: cause instanceof Error ? cause.message : fallbackMessage, + cause, + }); + const randomUUID = crypto.randomUUIDv4.pipe( + Effect.mapError((cause) => + toDispatchCommandError(cause, "Failed to generate orchestration command identifier."), + ), + ); + const serverEventId = randomUUID.pipe(Effect.map(EventId.make)); const serverCommandId = (tag: string) => randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`))); @@ -215,31 +227,28 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => readonly payload: Record; readonly tone: "info" | "error"; }) => - Effect.gen(function* () { - yield* orchestrationEngine.dispatch({ - type: "thread.activity.append", - commandId: yield* serverCommandId("setup-script-activity"), - threadId: input.threadId, - activity: { - id: EventId.make(yield* randomUUID), - tone: input.tone, - kind: input.kind, - summary: input.summary, - payload: input.payload, - turnId: null, + Effect.all({ + commandId: serverCommandId("setup-script-activity"), + activityId: serverEventId, + }).pipe( + Effect.flatMap(({ commandId, activityId }) => + orchestrationEngine.dispatch({ + type: "thread.activity.append", + commandId, + threadId: input.threadId, + activity: { + id: activityId, + tone: input.tone, + kind: input.kind, + summary: input.summary, + payload: input.payload, + turnId: null, + createdAt: input.createdAt, + }, createdAt: input.createdAt, - }, - createdAt: input.createdAt, - }); - }); - - const toDispatchCommandError = (cause: unknown, fallbackMessage: string) => - isOrchestrationDispatchCommandError(cause) - ? cause - : new OrchestrationDispatchCommandError({ - message: cause instanceof Error ? cause.message : fallbackMessage, - cause, - }); + }), + ), + ); const toBootstrapDispatchCommandCauseError = (cause: Cause.Cause) => { const error = Cause.squash(cause); @@ -375,13 +384,16 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => const cleanupCreatedThread = () => createdThread - ? Effect.gen(function* () { - yield* orchestrationEngine.dispatch({ - type: "thread.delete", - commandId: yield* serverCommandId("bootstrap-thread-delete"), - threadId: command.threadId, - }); - }).pipe(Effect.ignoreCause({ log: true })) + ? serverCommandId("bootstrap-thread-delete").pipe( + Effect.flatMap((commandId) => + orchestrationEngine.dispatch({ + type: "thread.delete", + commandId, + threadId: command.threadId, + }), + ), + Effect.ignoreCause({ log: true }), + ) : Effect.void; const recordSetupScriptLaunchFailure = (input: { diff --git a/bun.lock b/bun.lock index 2695cd8916d..ba82c97cb77 100644 --- a/bun.lock +++ b/bun.lock @@ -274,7 +274,7 @@ "@pierre/diffs": "1.1.20", "@types/bun": "^1.3.11", "@types/node": "^24.10.13", - "@typescript/native-preview": "7.0.0-dev.20260421.2", + "@typescript/native-preview": "7.0.0-dev.20260527.2", "effect": "4.0.0-beta.73", "tsdown": "^0.20.3", "typescript": "~6.0.3", @@ -927,21 +927,21 @@ "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="], - "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260421.2", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260421.2", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260421.2", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260421.2", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260421.2", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260421.2", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260421.2", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260421.2" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-CmajHI25HpVWE9R1XFoxr+cphJPxoYD3eFioQtAvXYkMFKnLdICMS9pXre9Pybizb75ejRxjKD5/CVG055rEIg=="], + "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260527.2", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260527.2", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260527.2", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260527.2", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260527.2", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260527.2", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260527.2", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260527.2" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-piqkDwikVeizCFqA1lcwI5F4wOAtBdxuliWe77ApBNRyBPPvfCJB+u/HYi9/8t5nd0sWvFs6/qt/AzJ1CCoykQ=="], - "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260421.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-fHv1r3ZmVo6zxuAIFmuX3w9QxbcauoG0SsWhmDwm6VmRubLlOJIcmTtlmV3JAb9oOnq8LuzZljzT7Q39fSMQDw=="], + "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260527.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-3LqSu4DlxkEfeC/Z/29QMCJn5jjkDtXI7LYuxfmjdmAatS6umDKqm8J17fnP/7fyrZUMBTIYRwSDpChGV3G1ew=="], - "@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260421.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-KWTR6xbW9t+JS7D5DQIzo75pqVXVWUxF9PMv/+S6xsnOjCVd6g0ixHcFpFMJMKSUQpGPr8Z5f7b8ks6LHW01jg=="], + "@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260527.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-H4+sxE9qaBbLF83wMdWE0FsgfK0Pom+/O+/oxqyGzhVkDJlNt3vfpgQZMit48/Gm44AacGfBggJ9Dhbi3aeSFw=="], - "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260421.2", "", { "os": "linux", "cpu": "arm" }, "sha512-BWLQO3nemLDSV5PoE5GPHe1dU9Dth77Kv8/cle9Ujcp4LhPo0KincdPqFH/qKeU/xvW25mgFueflZ1nc4rKuww=="], + "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260527.2", "", { "os": "linux", "cpu": "arm" }, "sha512-6I9Cv9ozwfS9zB9vRQDPIYseLX3artEO9jl3yVgLj4ishwlSF4cWAbIsjl5IztPaEgHv8coej/6tX1D0uaBzXg=="], - "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260421.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-VLMEuml3BhUb+jaL0TXQ4xvVODxJF+RhkI+tBWvlynsJI4khTXEiwWh+wPOJrsfBRYFRMXEu28Odl/HXkYze8w=="], + "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260527.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-BGUDMjC2Z3TTdZRkGGwhBLelkP5UYgO2rbep8aF4dS3fu7T5lFPPrnfS6EgqJgie+cF5Fsev7xEq8wWyBDM+lg=="], - "@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260421.2", "", { "os": "linux", "cpu": "x64" }, "sha512-qUrJWTB5/wv4wnRG0TRXElAxc2kykNiRNyEIEqBbLmzDlrcvAW7RRy8MXoY1ZyTiKGMu14itZ3x9oW6+blFpRw=="], + "@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260527.2", "", { "os": "linux", "cpu": "x64" }, "sha512-vpazOu+ozlxBo8U57YJMzsOPuxAV8H7fu36KJ8ea8At/D8pdGmOAy5TuB+9OBQV9JDe0OXJMy2kmbhOpmkTAmA=="], - "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260421.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Rc6NsWlZmCs5YUKVzKgwoBOoRUGsPzct4BDMRX0csD1devLBBc4AbUXWKsJRbpwIAnqMO1ld4sNHEb+wXgfNHQ=="], + "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260527.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-DBFnFE3V6AITkPO1K1VxXf3yEZKjU2FwtXlNwRqhzDu0rrL2SsJHOSrBDX+OacTxQFzZMxFcpiuhV8jHZALPEg=="], - "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260421.2", "", { "os": "win32", "cpu": "x64" }, "sha512-GQv1+dya1t6EqF2Cpsb+xoozovdX10JUSf6Kl/8xNkTapzmlHd+uMr+8ku3jIASTxoRGn0Mklgjj3MDKrOTuLg=="], + "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260527.2", "", { "os": "win32", "cpu": "x64" }, "sha512-1tBlErMvQgcMqqYwsx4tytupcjCJcOUXD3vBn1Wb/kAvus1FzWQAFE0fcKBvLfcqLQfTiiEwKKEtbLjGmakqqg=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], diff --git a/package.json b/package.json index 8235cbca100..d14f836646c 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@pierre/diffs": "1.1.20", "@types/bun": "^1.3.11", "@types/node": "^24.10.13", - "@typescript/native-preview": "7.0.0-dev.20260421.2", + "@typescript/native-preview": "7.0.0-dev.20260527.2", "tsdown": "^0.20.3", "typescript": "~6.0.3", "vitest": "^4.0.0" From 22ac454836fc18410bd85ffcd2470d2f8702f02d Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 15:06:37 -0700 Subject: [PATCH 05/10] Enforce Effect HTTP client usage in Effect code Co-authored-by: codex --- apps/server/src/server.test.ts | 348 ++++++++++++--------------------- apps/web/tsconfig.json | 3 +- tsconfig.base.json | 4 +- 3 files changed, 130 insertions(+), 225 deletions(-) diff --git a/apps/server/src/server.test.ts b/apps/server/src/server.test.ts index 48f3ffeb995..00b2ec025e8 100644 --- a/apps/server/src/server.test.ts +++ b/apps/server/src/server.test.ts @@ -37,10 +37,10 @@ import * as Layer from "effect/Layer"; import * as ManagedRuntime from "effect/ManagedRuntime"; import * as Option from "effect/Option"; import * as Path from "effect/Path"; -import * as Schema from "effect/Schema"; import * as Stream from "effect/Stream"; import { ChildProcessSpawner } from "effect/unstable/process"; import { + Cookies, FetchHttpClient, HttpBody, HttpClient, @@ -53,7 +53,6 @@ import * as Socket from "effect/unstable/socket/Socket"; import { vi } from "vitest"; const TEST_EPOCH = DateTime.makeUnsafe("1970-01-01T00:00:00.000Z"); -const encodeJsonRequestBody = Schema.encodeUnknownEffect(Schema.UnknownFromJsonString); import type { ServerConfigShape } from "./config.ts"; import { deriveServerPaths, ServerConfig } from "./config.ts"; @@ -782,13 +781,6 @@ const appendSessionCookieToWsUrl = (url: string, sessionCookieHeader: string) => return isAbsoluteUrl ? next.toString() : `${next.pathname}${next.search}${next.hash}`; }; -const getHttpServerUrl = (pathname = "") => - Effect.gen(function* () { - const server = yield* HttpServer.HttpServer; - const address = server.address as HttpServer.TcpAddress; - return `http://127.0.0.1:${address.port}${pathname}`; - }); - const bootstrapBrowserSession = ( credential = defaultDesktopBootstrapToken, options?: { @@ -796,19 +788,11 @@ const bootstrapBrowserSession = ( }, ) => Effect.gen(function* () { - const bootstrapUrl = yield* getHttpServerUrl("/api/auth/bootstrap"); - const requestBody = yield* encodeJsonRequestBody({ credential }); - const response = yield* Effect.promise(() => - fetch(bootstrapUrl, { - method: "POST", - headers: { - "content-type": "application/json", - ...options?.headers, - }, - body: requestBody, - }), - ); - const body = (yield* Effect.promise(() => response.json())) as { + const response = yield* HttpClient.post("/api/auth/bootstrap", { + headers: options?.headers, + body: yield* HttpBody.json({ credential }), + }); + const body = (yield* response.json) as { readonly authenticated: boolean; readonly sessionMethod: string; readonly expiresAt: string; @@ -816,7 +800,7 @@ const bootstrapBrowserSession = ( return { response, body, - cookie: response.headers.get("set-cookie"), + cookie: Cookies.toSetCookieHeaders(response.cookies)[0] ?? null, }; }); @@ -827,19 +811,11 @@ const bootstrapBearerSession = ( }, ) => Effect.gen(function* () { - const bootstrapUrl = yield* getHttpServerUrl("/api/auth/bootstrap/bearer"); - const requestBody = yield* encodeJsonRequestBody({ credential }); - const response = yield* Effect.promise(() => - fetch(bootstrapUrl, { - method: "POST", - headers: { - "content-type": "application/json", - ...options?.headers, - }, - body: requestBody, - }), - ); - const body = (yield* Effect.promise(() => response.json())) as { + const response = yield* HttpClient.post("/api/auth/bootstrap/bearer", { + headers: options?.headers, + body: yield* HttpBody.json({ credential }), + }); + const body = (yield* response.json) as { readonly authenticated: boolean; readonly sessionMethod: string; readonly expiresAt: string; @@ -859,7 +835,7 @@ class AuthenticationGetterError extends Data.TaggedError("AuthenticationGetterEr const getAuthenticatedSessionCookieHeader = (credential = defaultDesktopBootstrapToken) => Effect.gen(function* () { const { response, cookie } = yield* bootstrapBrowserSession(credential); - if (!response.ok) { + if (response.status !== 200) { return yield* new AuthenticationGetterError({ message: `Expected bootstrap session response to succeed, got ${response.status}`, }); @@ -877,7 +853,7 @@ const getAuthenticatedSessionCookieHeader = (credential = defaultDesktopBootstra const getAuthenticatedBearerSessionToken = (credential = defaultDesktopBootstrapToken) => Effect.gen(function* () { const { response, body } = yield* bootstrapBearerSession(credential); - if (!response.ok) { + if (response.status !== 200) { return yield* new AuthenticationGetterError({ message: `Expected bearer bootstrap response to succeed, got ${response.status}`, }); @@ -908,14 +884,14 @@ const splitHeaderTokens = (value: string | null) => .filter((token) => token.length > 0) .toSorted(); -const assertBrowserApiCorsHeaders = (headers: Headers) => { - assert.equal(headers.get("access-control-allow-origin"), "*"); - assert.deepEqual(splitHeaderTokens(headers.get("access-control-allow-methods")), [ +const assertBrowserApiCorsHeaders = (headers: Readonly>) => { + assert.equal(headers["access-control-allow-origin"], "*"); + assert.deepEqual(splitHeaderTokens(headers["access-control-allow-methods"] ?? null), [ "GET", "OPTIONS", "POST", ]); - assert.deepEqual(splitHeaderTokens(headers.get("access-control-allow-headers")), [ + assert.deepEqual(splitHeaderTokens(headers["access-control-allow-headers"] ?? null), [ "authorization", "b3", "content-type", @@ -964,14 +940,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { config: { devUrl: new URL("http://127.0.0.1:5173") }, }); - const url = yield* getHttpServerUrl("/foo/bar?token=test-token"); - const response = yield* Effect.promise(() => fetch(url, { redirect: "manual" })); + const response = yield* HttpClient.get("/foo/bar?token=test-token").pipe( + Effect.provideService(FetchHttpClient.RequestInit, { redirect: "manual" }), + ); assert.equal(response.status, 302); - assert.equal( - response.headers.get("location"), - "http://127.0.0.1:5173/foo/bar?token=test-token", - ); + assert.equal(response.headers.location, "http://127.0.0.1:5173/foo/bar?token=test-token"); }).pipe(Effect.provide(NodeHttpServer.layerTest)), ); @@ -1034,11 +1008,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const url = yield* getHttpServerUrl("/.well-known/t3/environment"); - const response = yield* Effect.promise(() => fetch(url)); - const body = (yield* Effect.promise(() => - response.json(), - )) as typeof testEnvironmentDescriptor; + const response = yield* HttpClient.get("/.well-known/t3/environment"); + const body = (yield* response.json) as typeof testEnvironmentDescriptor; assert.equal(response.status, 200); assert.deepEqual(body, testEnvironmentDescriptor); @@ -1049,17 +1020,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const url = yield* getHttpServerUrl("/.well-known/t3/environment"); - const response = yield* Effect.promise(() => - fetch(url, { - headers: { - origin: crossOriginClientOrigin, - }, - }), - ); - const body = (yield* Effect.promise(() => - response.json(), - )) as typeof testEnvironmentDescriptor; + const response = yield* HttpClient.get("/.well-known/t3/environment", { + headers: { + origin: crossOriginClientOrigin, + }, + }); + const body = (yield* response.json) as typeof testEnvironmentDescriptor; assert.equal(response.status, 200); assertBrowserApiCorsHeaders(response.headers); @@ -1071,9 +1037,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const url = yield* getHttpServerUrl("/api/auth/session"); - const response = yield* Effect.promise(() => fetch(url)); - const body = (yield* Effect.promise(() => response.json())) as { + const response = yield* HttpClient.get("/api/auth/session"); + const body = (yield* response.json) as { readonly authenticated: boolean; readonly auth: { readonly policy: string; @@ -1111,15 +1076,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.isUndefined((bootstrapBody as { readonly sessionToken?: string }).sessionToken); assert.isDefined(setCookie); - const sessionUrl = yield* getHttpServerUrl("/api/auth/session"); - const sessionResponse = yield* Effect.promise(() => - fetch(sessionUrl, { - headers: { - cookie: setCookie?.split(";")[0] ?? "", - }, - }), - ); - const sessionBody = (yield* Effect.promise(() => sessionResponse.json())) as { + const sessionResponse = yield* HttpClient.get("/api/auth/session", { + headers: { + cookie: setCookie?.split(";")[0] ?? "", + }, + }); + const sessionBody = (yield* sessionResponse.json) as { readonly authenticated: boolean; readonly sessionMethod?: string; }; @@ -1145,15 +1107,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(typeof bootstrapBody.sessionToken, "string"); assert.isTrue((bootstrapBody.sessionToken?.length ?? 0) > 0); - const sessionUrl = yield* getHttpServerUrl("/api/auth/session"); - const sessionResponse = yield* Effect.promise(() => - fetch(sessionUrl, { - headers: { - authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`, - }, - }), - ); - const sessionBody = (yield* Effect.promise(() => sessionResponse.json())) as { + const sessionResponse = yield* HttpClient.get("/api/auth/session", { + headers: { + authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`, + }, + }); + const sessionBody = (yield* sessionResponse.json) as { readonly authenticated: boolean; readonly sessionMethod?: string; }; @@ -1169,16 +1128,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { yield* buildAppUnderTest(); const bearerToken = yield* getAuthenticatedBearerSessionToken(); - const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token"); - const wsTokenResponse = yield* Effect.promise(() => - fetch(wsTokenUrl, { - method: "POST", - headers: { - authorization: `Bearer ${bearerToken}`, - }, - }), - ); - const wsTokenBody = (yield* Effect.promise(() => wsTokenResponse.json())) as { + const wsTokenResponse = yield* HttpClient.post("/api/auth/ws-token", { + headers: { + authorization: `Bearer ${bearerToken}`, + }, + }); + const wsTokenBody = (yield* wsTokenResponse.json) as { readonly token: string; readonly expiresAt: string; }; @@ -1207,16 +1162,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(bootstrapBody.authenticated, true); assert.equal(typeof bootstrapBody.sessionToken, "string"); - const sessionUrl = yield* getHttpServerUrl("/api/auth/session"); - const sessionResponse = yield* Effect.promise(() => - fetch(sessionUrl, { - headers: { - authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`, - origin, - }, - }), - ); - const sessionBody = (yield* Effect.promise(() => sessionResponse.json())) as { + const sessionResponse = yield* HttpClient.get("/api/auth/session", { + headers: { + authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`, + origin, + }, + }); + const sessionBody = (yield* sessionResponse.json) as { readonly authenticated: boolean; readonly sessionMethod?: string; }; @@ -1226,17 +1178,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(sessionBody.authenticated, true); assert.equal(sessionBody.sessionMethod, "bearer-session-token"); - const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token"); - const wsTokenResponse = yield* Effect.promise(() => - fetch(wsTokenUrl, { - method: "POST", - headers: { - authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`, - origin, - }, - }), - ); - const wsTokenBody = (yield* Effect.promise(() => wsTokenResponse.json())) as { + const wsTokenResponse = yield* HttpClient.post("/api/auth/ws-token", { + headers: { + authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`, + origin, + }, + }); + const wsTokenBody = (yield* wsTokenResponse.json) as { readonly token: string; }; @@ -1252,17 +1200,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token"); - const response = yield* Effect.promise(() => - fetch(wsTokenUrl, { - method: "OPTIONS", - headers: { - origin: crossOriginClientOrigin, - "access-control-request-method": "POST", - "access-control-request-headers": "authorization", - }, - }), - ); + const response = yield* HttpClient.options("/api/auth/ws-token", { + headers: { + origin: crossOriginClientOrigin, + "access-control-request-method": "POST", + "access-control-request-headers": "authorization", + }, + }); assert.equal(response.status, 204); assertBrowserApiCorsHeaders(response.headers); @@ -1273,16 +1217,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token"); - const response = yield* Effect.promise(() => - fetch(wsTokenUrl, { - method: "POST", - headers: { - origin: crossOriginClientOrigin, - }, - }), - ); - const body = (yield* Effect.promise(() => response.json())) as { + const response = yield* HttpClient.post("/api/auth/ws-token", { + headers: { + origin: crossOriginClientOrigin, + }, + }); + const body = (yield* response.json) as { readonly error?: string; }; @@ -1357,18 +1297,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { readonly credential: string; }>; - const revokeUrl = yield* getHttpServerUrl("/api/auth/pairing-links/revoke"); - const revokeBody = yield* encodeJsonRequestBody({ id: createdBody.id }); - const revokeResponse = yield* Effect.promise(() => - fetch(revokeUrl, { - method: "POST", - headers: { - cookie: ownerCookie, - "content-type": "application/json", - }, - body: revokeBody, - }), - ); + const revokeResponse = yield* HttpClient.post("/api/auth/pairing-links/revoke", { + headers: { + cookie: ownerCookie, + }, + body: yield* HttpBody.json({ id: createdBody.id }), + }); const revokedBootstrap = yield* bootstrapBrowserSession(createdBody.credential); assert.equal(createdResponse.status, 200); @@ -1421,21 +1355,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => { }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const pairingTokenUrl = yield* getHttpServerUrl("/api/auth/pairing-token"); - const ownerPairingBodyInput = yield* encodeJsonRequestBody({ - label: "Julius iPhone", + const ownerPairingResponse = yield* HttpClient.post("/api/auth/pairing-token", { + headers: { + cookie: ownerCookie, + }, + body: yield* HttpBody.json({ label: "Julius iPhone" }), }); - const ownerPairingResponse = yield* Effect.promise(() => - fetch(pairingTokenUrl, { - method: "POST", - headers: { - cookie: ownerCookie, - "content-type": "application/json", - }, - body: ownerPairingBodyInput, - }), - ); - const ownerPairingBody = (yield* Effect.promise(() => ownerPairingResponse.json())) as { + const ownerPairingBody = (yield* ownerPairingResponse.json) as { readonly credential: string; readonly label?: string; }; @@ -1450,17 +1376,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.isDefined(pairedSessionCookie); const pairedSessionCookieHeader = pairedSessionCookie ?? ""; - const listClientsUrl = yield* getHttpServerUrl("/api/auth/clients"); - const listBeforeResponse = yield* Effect.promise(() => - fetch(listClientsUrl, { - headers: { - cookie: ownerCookie, - }, - }), - ); - const clientsBefore = (yield* Effect.promise(() => - listBeforeResponse.json(), - )) as ReadonlyArray<{ + const listBeforeResponse = yield* HttpClient.get("/api/auth/clients", { + headers: { + cookie: ownerCookie, + }, + }); + const clientsBefore = (yield* listBeforeResponse.json) as ReadonlyArray<{ readonly sessionId: string; readonly current: boolean; readonly client: { @@ -1557,18 +1478,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { const pairedSessionId = clients.find((entry) => !entry.current)?.sessionId; assert.isDefined(pairedSessionId); - const revokeUrl = yield* getHttpServerUrl("/api/auth/clients/revoke"); - const revokeBody = yield* encodeJsonRequestBody({ sessionId: pairedSessionId }); - const revokeResponse = yield* Effect.promise(() => - fetch(revokeUrl, { - method: "POST", - headers: { - cookie: ownerCookie, - "content-type": "application/json", - }, - body: revokeBody, - }), - ); + const revokeResponse = yield* HttpClient.post("/api/auth/clients/revoke", { + headers: { + cookie: ownerCookie, + }, + body: yield* HttpBody.json({ sessionId: pairedSessionId }), + }); const pairedClientPairingResponse = yield* HttpClient.post("/api/auth/pairing-token", { headers: { cookie: pairedSessionCookie, @@ -1668,16 +1583,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => { yield* buildAppUnderTest(); const bearerToken = yield* getAuthenticatedBearerSessionToken(); - const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token"); - const wsTokenResponse = yield* Effect.promise(() => - fetch(wsTokenUrl, { - method: "POST", - headers: { - authorization: `Bearer ${bearerToken}`, - }, - }), - ); - const wsTokenBody = (yield* Effect.promise(() => wsTokenResponse.json())) as { + const wsTokenResponse = yield* HttpClient.post("/api/auth/ws-token", { + headers: { + authorization: `Bearer ${bearerToken}`, + }, + }); + const wsTokenBody = (yield* wsTokenResponse.json) as { readonly token: string; }; const wsUrl = `${yield* getWsServerUrl("/ws", { authenticated: false })}?wsToken=${encodeURIComponent(wsTokenBody.token)}`; @@ -1879,8 +1790,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { "content-type": "application/json", origin: "http://localhost:5733", }, - // @effect-diagnostics-next-line preferSchemaOverJson:off - body: HttpBody.text(JSON.stringify(payload), "application/json"), + body: yield* HttpBody.json(payload), }); assert.equal(response.status, 204); @@ -1937,31 +1847,24 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const url = yield* getHttpServerUrl("/api/observability/v1/traces"); - const response = yield* Effect.promise(() => - fetch(url, { - method: "OPTIONS", - headers: { - origin: "http://localhost:5733", - "access-control-request-method": "POST", - "access-control-request-headers": "content-type", - }, - }), - ); + const response = yield* HttpClient.options("/api/observability/v1/traces", { + headers: { + origin: "http://localhost:5733", + "access-control-request-method": "POST", + "access-control-request-headers": "content-type", + }, + }); assert.equal(response.status, 204); - assert.equal(response.headers.get("access-control-allow-origin"), "*"); - assert.deepEqual(splitHeaderTokens(response.headers.get("access-control-allow-methods")), [ - "GET", - "OPTIONS", - "POST", - ]); - assert.deepEqual(splitHeaderTokens(response.headers.get("access-control-allow-headers")), [ - "authorization", - "b3", - "content-type", - "traceparent", - ]); + assert.equal(response.headers["access-control-allow-origin"], "*"); + assert.deepEqual( + splitHeaderTokens(response.headers["access-control-allow-methods"] ?? null), + ["GET", "OPTIONS", "POST"], + ); + assert.deepEqual( + splitHeaderTokens(response.headers["access-control-allow-headers"] ?? null), + ["authorization", "b3", "content-type", "traceparent"], + ); }).pipe(Effect.provide(NodeHttpServer.layerTest)), ); @@ -1998,8 +1901,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { cookie: yield* getAuthenticatedSessionCookieHeader(), "content-type": "application/json", }, - // @effect-diagnostics-next-line preferSchemaOverJson:off - body: HttpBody.text(JSON.stringify(payload), "application/json"), + body: yield* HttpBody.json(payload), }); assert.equal(response.status, 204); diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 8d6954ae0f0..98505f0d1a0 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -34,7 +34,8 @@ "globalDate": "off", "globalConsole": "off", "globalRandom": "off", - "globalTimers": "off" + "globalTimers": "off", + "globalFetch": "off" } } ] diff --git a/tsconfig.base.json b/tsconfig.base.json index 4f7edbaf759..e68fce2d699 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -47,7 +47,9 @@ "globalRandom": "error", "globalRandomInEffect": "error", "globalTimers": "error", - "globalTimersInEffect": "error" + "globalTimersInEffect": "error", + "globalFetch": "error", + "globalFetchInEffect": "error" } } ] From a0ca1f589c1b1f20f2fdb9beea8c18f4d7f439ae Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 15:09:50 -0700 Subject: [PATCH 06/10] Remove unnecessary Effect generator wrappers Co-authored-by: codex --- .../src/app/DesktopEnvironment.test.ts | 4 +-- .../009_ProviderSessionRuntimeMode.ts | 4 +-- .../provider/Layers/ProviderService.test.ts | 8 ++--- .../src/textGeneration/CodexTextGeneration.ts | 34 +++++++++---------- 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/apps/desktop/src/app/DesktopEnvironment.test.ts b/apps/desktop/src/app/DesktopEnvironment.test.ts index 427b8848833..11ea03f6816 100644 --- a/apps/desktop/src/app/DesktopEnvironment.test.ts +++ b/apps/desktop/src/app/DesktopEnvironment.test.ts @@ -32,9 +32,7 @@ const makeEnvironment = ( overrides: Partial = {}, env: Record = {}, ) => - Effect.gen(function* () { - return yield* DesktopEnvironment.DesktopEnvironment; - }).pipe(Effect.provide(makeEnvironmentLayer(overrides, env))); + DesktopEnvironment.DesktopEnvironment.pipe(Effect.provide(makeEnvironmentLayer(overrides, env))); describe("DesktopEnvironment", () => { it.effect("derives state paths and development identity inside Effect", () => diff --git a/apps/server/src/persistence/Migrations/009_ProviderSessionRuntimeMode.ts b/apps/server/src/persistence/Migrations/009_ProviderSessionRuntimeMode.ts index 3f7249e873f..50b556d39af 100644 --- a/apps/server/src/persistence/Migrations/009_ProviderSessionRuntimeMode.ts +++ b/apps/server/src/persistence/Migrations/009_ProviderSessionRuntimeMode.ts @@ -1,6 +1,4 @@ import * as SqlClient from "effect/unstable/sql/SqlClient"; import * as Effect from "effect/Effect"; -export default Effect.gen(function* () { - yield* SqlClient.SqlClient; -}); +export default Effect.asVoid(SqlClient.SqlClient); diff --git a/apps/server/src/provider/Layers/ProviderService.test.ts b/apps/server/src/provider/Layers/ProviderService.test.ts index fc0450b8b69..6a72bf69941 100644 --- a/apps/server/src/provider/Layers/ProviderService.test.ts +++ b/apps/server/src/provider/Layers/ProviderService.test.ts @@ -346,9 +346,7 @@ it.effect("ProviderServiceLive catches stopAll failures during shutdown", () => const scope = yield* Scope.make(); const runtimeServices = yield* Layer.build(providerLayer).pipe(Scope.provide(scope)); - yield* Effect.gen(function* () { - yield* ProviderService; - }).pipe(Effect.provide(runtimeServices)); + yield* ProviderService.pipe(Effect.provide(runtimeServices)); const closeExit = yield* Scope.close(scope, Exit.void).pipe(Effect.exit); assert.equal(Exit.isSuccess(closeExit), true); @@ -636,9 +634,7 @@ it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", ( Layer.provide(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), ); - yield* Effect.gen(function* () { - yield* ProviderService; - }).pipe(Effect.provide(providerLayer)); + yield* ProviderService.pipe(Effect.provide(providerLayer)); const persistedProvider = yield* Effect.gen(function* () { const directory = yield* ProviderSessionDirectory; diff --git a/apps/server/src/textGeneration/CodexTextGeneration.ts b/apps/server/src/textGeneration/CodexTextGeneration.ts index db2f47ca565..7f400d9ce50 100644 --- a/apps/server/src/textGeneration/CodexTextGeneration.ts +++ b/apps/server/src/textGeneration/CodexTextGeneration.ts @@ -76,24 +76,22 @@ export const makeCodexTextGeneration = Effect.fn("makeCodexTextGeneration")(func operation: string, prefix: string, content: string, - ): Effect.Effect => { - return Effect.gen(function* () { - return yield* fileSystem - .makeTempFileScoped({ - prefix: `t3code-${prefix}-${process.pid}-`, - }) - .pipe(Effect.tap((filePath) => fileSystem.writeFileString(filePath, content))); - }).pipe( - Effect.mapError( - (cause) => - new TextGenerationError({ - operation, - detail: `Failed to write temp file`, - cause, - }), - ), - ); - }; + ): Effect.Effect => + fileSystem + .makeTempFileScoped({ + prefix: `t3code-${prefix}-${process.pid}-`, + }) + .pipe( + Effect.tap((filePath) => fileSystem.writeFileString(filePath, content)), + Effect.mapError( + (cause) => + new TextGenerationError({ + operation, + detail: `Failed to write temp file`, + cause, + }), + ), + ); const safeUnlink = (filePath: string): Effect.Effect => fileSystem.remove(filePath).pipe(Effect.catch(() => Effect.void)); From fbe1d6271badaff60c0719910191735df502b571 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 15:28:06 -0700 Subject: [PATCH 07/10] Decode lenient JSON through Effect Schema Co-authored-by: codex --- packages/shared/src/schemaJson.test.ts | 4 +++ packages/shared/src/schemaJson.ts | 50 +++++++++++++------------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/packages/shared/src/schemaJson.test.ts b/packages/shared/src/schemaJson.test.ts index 1874c0d9b03..ed2abe363f1 100644 --- a/packages/shared/src/schemaJson.test.ts +++ b/packages/shared/src/schemaJson.test.ts @@ -44,4 +44,8 @@ Done.`), values: [1, 2], }); }); + + it("rejects malformed JSON after lenient preprocessing", () => { + expect(() => decodeLenientJson('{ "enabled": true,, }')).toThrow(); + }); }); diff --git a/packages/shared/src/schemaJson.ts b/packages/shared/src/schemaJson.ts index f2deb891401..8b76d9e0a2d 100644 --- a/packages/shared/src/schemaJson.ts +++ b/packages/shared/src/schemaJson.ts @@ -47,31 +47,31 @@ export const formatSchemaError = (cause: Cause.Cause) => { * * Mirrors `SchemaGetter.parseJson()` but strips JSONC syntax before parsing. */ -const decodeUnknownJsonString = Schema.decodeUnknownSync(Schema.UnknownFromJsonString); - -const parseLenientJsonGetter = SchemaGetter.onSome((input: string) => - Effect.try({ - try: () => { - // Strip single-line comments — alternation preserves quoted strings. - let stripped = input.replace( - /("(?:[^"\\]|\\.)*")|\/\/[^\n]*/g, - (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""), - ); - - // Strip multi-line comments. - stripped = stripped.replace( - /("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g, - (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""), - ); - - // Strip trailing commas before `}` or `]`. - stripped = stripped.replace(/,(\s*[}\]])/g, "$1"); - - return Option.some(decodeUnknownJsonString(stripped)); - }, - catch: (e) => new SchemaIssue.InvalidValue(Option.some(input), { message: String(e) }), - }), -); +const decodeJsonString = Schema.decodeEffect(Schema.UnknownFromJsonString); + +const parseLenientJsonGetter = SchemaGetter.onSome((input: string) => { + // Strip single-line comments - alternation preserves quoted strings. + let stripped = input.replace( + /("(?:[^"\\]|\\.)*")|\/\/[^\n]*/g, + (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""), + ); + + // Strip multi-line comments. + stripped = stripped.replace( + /("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g, + (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""), + ); + + // Strip trailing commas before `}` or `]`. + stripped = stripped.replace(/,(\s*[}\]])/g, "$1"); + + return decodeJsonString(stripped).pipe( + Effect.map(Option.some), + Effect.mapError( + (error) => new SchemaIssue.InvalidValue(Option.some(input), { message: String(error) }), + ), + ); +}); /** * Schema transformation: lenient JSONC string ↔ unknown. From 97911119cc6cd24b2aadc13da83f40ed18ed4b1b Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 15:41:47 -0700 Subject: [PATCH 08/10] Resolve remaining TSGo suggestions Co-authored-by: codex --- apps/server/src/orchestration/http.ts | 6 +- .../src/persistence/Layers/AuthSessions.ts | 2 +- .../src/provider/Layers/CursorAdapter.ts | 2 +- .../src/provider/Layers/OpenCodeProvider.ts | 48 +- packages/effect-acp/scripts/generate.ts | 9 +- packages/effect-acp/src/protocol.ts | 4 +- .../scripts/generate.ts | 27 +- .../src/_generated/meta.gen.ts | 466 +++++++++--------- tsconfig.base.json | 1 + 9 files changed, 276 insertions(+), 289 deletions(-) diff --git a/apps/server/src/orchestration/http.ts b/apps/server/src/orchestration/http.ts index f24f808c6f8..aaf3a3a108b 100644 --- a/apps/server/src/orchestration/http.ts +++ b/apps/server/src/orchestration/http.ts @@ -58,8 +58,10 @@ export const orchestrationSnapshotRouteLayer = HttpRouter.add( status: 200, }); }).pipe( - Effect.catchTag("OrchestrationDispatchCommandError", respondToOrchestrationHttpError), - Effect.catchTag("OrchestrationGetSnapshotError", respondToOrchestrationHttpError), + Effect.catchTags({ + OrchestrationDispatchCommandError: respondToOrchestrationHttpError, + OrchestrationGetSnapshotError: respondToOrchestrationHttpError, + }), ), ); diff --git a/apps/server/src/persistence/Layers/AuthSessions.ts b/apps/server/src/persistence/Layers/AuthSessions.ts index 64b8146f927..6774e79c81a 100644 --- a/apps/server/src/persistence/Layers/AuthSessions.ts +++ b/apps/server/src/persistence/Layers/AuthSessions.ts @@ -40,7 +40,7 @@ const AuthSessionDbRow = Schema.Struct({ revokedAt: Schema.NullOr(Schema.DateTimeUtcFromString), }); -function toAuthSessionRecord(row: typeof AuthSessionDbRow.Type): typeof AuthSessionRecord.Type { +function toAuthSessionRecord(row: typeof AuthSessionDbRow.Type): AuthSessionRecord { return { sessionId: row.sessionId, subject: row.subject, diff --git a/apps/server/src/provider/Layers/CursorAdapter.ts b/apps/server/src/provider/Layers/CursorAdapter.ts index 0671af0d4e8..016feeb79a4 100644 --- a/apps/server/src/provider/Layers/CursorAdapter.ts +++ b/apps/server/src/provider/Layers/CursorAdapter.ts @@ -97,7 +97,7 @@ export interface CursorAdapterLiveOptions { * Selections are honored when `modelSelection.instanceId` matches this value. * Defaults to the legacy built-in instance id (`cursor`). */ - readonly instanceId?: typeof ProviderInstanceId.Type; + readonly instanceId?: ProviderInstanceId; /** * Optional per-session settings resolver. When provided the adapter yields * this effect at the start of every session and uses the result instead of diff --git a/apps/server/src/provider/Layers/OpenCodeProvider.ts b/apps/server/src/provider/Layers/OpenCodeProvider.ts index dea95c990d2..fa436b5fbe0 100644 --- a/apps/server/src/provider/Layers/OpenCodeProvider.ts +++ b/apps/server/src/provider/Layers/OpenCodeProvider.ts @@ -408,35 +408,25 @@ export const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatu const inventoryExit = yield* Effect.exit( Effect.scoped( Effect.gen(function* () { - const server = yield* openCodeRuntime - .connectToOpenCodeServer({ - binaryPath: openCodeSettings.binaryPath, - serverUrl: openCodeSettings.serverUrl, - environment, - }) - .pipe( - Effect.mapError( - (cause) => - new OpenCodeProbeError({ cause, detail: openCodeRuntimeErrorDetail(cause) }), - ), - ); - return yield* openCodeRuntime - .loadOpenCodeInventory( - openCodeRuntime.createOpenCodeSdkClient({ - baseUrl: server.url, - directory: cwd, - ...(isExternalServer && openCodeSettings.serverPassword - ? { serverPassword: openCodeSettings.serverPassword } - : {}), - }), - ) - .pipe( - Effect.mapError( - (cause) => - new OpenCodeProbeError({ cause, detail: openCodeRuntimeErrorDetail(cause) }), - ), - ); - }), + const server = yield* openCodeRuntime.connectToOpenCodeServer({ + binaryPath: openCodeSettings.binaryPath, + serverUrl: openCodeSettings.serverUrl, + environment, + }); + return yield* openCodeRuntime.loadOpenCodeInventory( + openCodeRuntime.createOpenCodeSdkClient({ + baseUrl: server.url, + directory: cwd, + ...(isExternalServer && openCodeSettings.serverPassword + ? { serverPassword: openCodeSettings.serverPassword } + : {}), + }), + ); + }).pipe( + Effect.mapError( + (cause) => new OpenCodeProbeError({ cause, detail: openCodeRuntimeErrorDetail(cause) }), + ), + ), ), ); if (inventoryExit._tag === "Failure") { diff --git a/packages/effect-acp/scripts/generate.ts b/packages/effect-acp/scripts/generate.ts index 374f636df1e..1fe8e2edf8a 100644 --- a/packages/effect-acp/scripts/generate.ts +++ b/packages/effect-acp/scripts/generate.ts @@ -146,7 +146,7 @@ function collectSchemaEntries( return entries; } -function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.Json.Type { +function normalizeNullableTypes(value: Schema.Json): Schema.Json { if (Array.isArray(value)) { return value.map(normalizeNullableTypes); } @@ -158,10 +158,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J key, normalizeNullableTypes(child), ]); - const normalizedObject = Object.fromEntries(normalizedEntries) as Record< - string, - typeof Schema.Json.Type - >; + const normalizedObject = Object.fromEntries(normalizedEntries) as Record; const typeValue = normalizedObject.type; if (!Array.isArray(typeValue)) { @@ -179,7 +176,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J } const nonNullType = nonNullTypes[0]!; - const nextObject: Record = {}; + const nextObject: Record = {}; for (const [key, child] of Object.entries(normalizedObject)) { if (key !== "type") { nextObject[key] = child; diff --git a/packages/effect-acp/src/protocol.ts b/packages/effect-acp/src/protocol.ts index 52d6eafd6d5..56a7ce81ab8 100644 --- a/packages/effect-acp/src/protocol.ts +++ b/packages/effect-acp/src/protocol.ts @@ -29,12 +29,12 @@ export type AcpIncomingNotification = | { readonly _tag: "SessionUpdate"; readonly method: typeof CLIENT_METHODS.session_update; - readonly params: typeof AcpSchema.SessionNotification.Type; + readonly params: AcpSchema.SessionNotification; } | { readonly _tag: "ElicitationComplete"; readonly method: typeof CLIENT_METHODS.session_elicitation_complete; - readonly params: typeof AcpSchema.ElicitationCompleteNotification.Type; + readonly params: AcpSchema.ElicitationCompleteNotification; } | { readonly _tag: "ExtNotification"; diff --git a/packages/effect-codex-app-server/scripts/generate.ts b/packages/effect-codex-app-server/scripts/generate.ts index d12caa3464b..79b8c32c4c9 100644 --- a/packages/effect-codex-app-server/scripts/generate.ts +++ b/packages/effect-codex-app-server/scripts/generate.ts @@ -70,7 +70,7 @@ class GeneratorError extends Schema.TaggedErrorClass()("Generato } } -const ManualSchemas: Record = { +const ManualSchemas: Record = { GetAuthStatusParams: { type: "object", title: "GetAuthStatusParams", @@ -218,7 +218,7 @@ function collectSchemaEntries( return entries; } -function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.Json.Type { +function normalizeNullableTypes(value: Schema.Json): Schema.Json { if (Array.isArray(value)) { return value.map(normalizeNullableTypes); } @@ -230,10 +230,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J key, normalizeNullableTypes(child), ]); - const normalizedObject = Object.fromEntries(normalizedEntries) as Record< - string, - typeof Schema.Json.Type - >; + const normalizedObject = Object.fromEntries(normalizedEntries) as Record; const typeValue = normalizedObject.type; if (!Array.isArray(typeValue)) { @@ -251,7 +248,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J } const nonNullType = nonNullTypes[0]!; - const nextObject: Record = {}; + const nextObject: Record = {}; for (const [key, child] of Object.entries(normalizedObject)) { if (key !== "type") { nextObject[key] = child; @@ -269,7 +266,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J }; } -function stripNullDefaults(value: typeof Schema.Json.Type): typeof Schema.Json.Type { +function stripNullDefaults(value: Schema.Json): Schema.Json { if (Array.isArray(value)) { return value.map(stripNullDefaults); } @@ -281,7 +278,7 @@ function stripNullDefaults(value: typeof Schema.Json.Type): typeof Schema.Json.T Object.entries(value) .filter(([key, child]) => !(key === "default" && child === null)) .map(([key, child]) => [key, stripNullDefaults(child)]), - ) as typeof Schema.Json.Type; + ) as Schema.Json; } function toPascalCaseMethod(method: string) { @@ -417,7 +414,7 @@ function renderSchemaMap( } function renderSchemaTypeReference(schemaName: string) { - return schemaName === "undefined" ? "undefined" : `typeof CodexSchema.${schemaName}.Type`; + return schemaName === "undefined" ? "undefined" : `CodexSchema.${schemaName}`; } function exportNameForPath(filePath: string): string { @@ -468,11 +465,11 @@ function buildJsonSchemaFiles( } function rewriteExternalRefs( - value: typeof Schema.Json.Type, + value: Schema.Json, localDefinitionNames: ReadonlyMap, currentNamespace: string | undefined, exportNameByQualifiedName: ReadonlyMap, -): typeof Schema.Json.Type { +): Schema.Json { if (Array.isArray(value)) { return value.map((entry) => rewriteExternalRefs(entry, localDefinitionNames, currentNamespace, exportNameByQualifiedName), @@ -522,7 +519,7 @@ function rewriteExternalRefs( ), ]; }), - ) as typeof Schema.Json.Type; + ) as Schema.Json; } const generateFiles = Effect.fn("generateFiles")(function* () { @@ -543,7 +540,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () { const exportNameByQualifiedName = new Map( jsonSchemaFiles.map((file) => [file.qualifiedName, file.exportName]), ); - const aggregateSchemas: Record = {}; + const aggregateSchemas: Record = {}; for (const file of jsonSchemaFiles) { const raw = yield* fetchText(file.downloadUrl); @@ -568,7 +565,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () { ); } - const topLevelSchema: Record = {}; + const topLevelSchema: Record = {}; for (const [key, value] of Object.entries(parsed)) { if (key !== "definitions") { topLevelSchema[key] = value; diff --git a/packages/effect-codex-app-server/src/_generated/meta.gen.ts b/packages/effect-codex-app-server/src/_generated/meta.gen.ts index b6c0b00d1c2..12c386216b1 100644 --- a/packages/effect-codex-app-server/src/_generated/meta.gen.ts +++ b/packages/effect-codex-app-server/src/_generated/meta.gen.ts @@ -173,165 +173,165 @@ export type ServerRequestMethod = keyof typeof SERVER_REQUEST_METHODS; export type ServerNotificationMethod = keyof typeof SERVER_NOTIFICATION_METHODS; export interface ClientRequestParamsByMethod { - readonly initialize: typeof CodexSchema.V1InitializeParams.Type; - readonly "thread/start": typeof CodexSchema.V2ThreadStartParams.Type; - readonly "thread/resume": typeof CodexSchema.V2ThreadResumeParams.Type; - readonly "thread/fork": typeof CodexSchema.V2ThreadForkParams.Type; - readonly "thread/archive": typeof CodexSchema.V2ThreadArchiveParams.Type; - readonly "thread/unsubscribe": typeof CodexSchema.V2ThreadUnsubscribeParams.Type; - readonly "thread/name/set": typeof CodexSchema.V2ThreadSetNameParams.Type; - readonly "thread/metadata/update": typeof CodexSchema.V2ThreadMetadataUpdateParams.Type; - readonly "thread/unarchive": typeof CodexSchema.V2ThreadUnarchiveParams.Type; - readonly "thread/compact/start": typeof CodexSchema.V2ThreadCompactStartParams.Type; - readonly "thread/shellCommand": typeof CodexSchema.V2ThreadShellCommandParams.Type; - readonly "thread/approveGuardianDeniedAction": typeof CodexSchema.V2ThreadApproveGuardianDeniedActionParams.Type; - readonly "thread/rollback": typeof CodexSchema.V2ThreadRollbackParams.Type; - readonly "thread/list": typeof CodexSchema.V2ThreadListParams.Type; - readonly "thread/loaded/list": typeof CodexSchema.V2ThreadLoadedListParams.Type; - readonly "thread/read": typeof CodexSchema.V2ThreadReadParams.Type; - readonly "thread/inject_items": typeof CodexSchema.V2ThreadInjectItemsParams.Type; - readonly "skills/list": typeof CodexSchema.V2SkillsListParams.Type; - readonly "hooks/list": typeof CodexSchema.V2HooksListParams.Type; - readonly "marketplace/add": typeof CodexSchema.V2MarketplaceAddParams.Type; - readonly "marketplace/remove": typeof CodexSchema.V2MarketplaceRemoveParams.Type; - readonly "marketplace/upgrade": typeof CodexSchema.V2MarketplaceUpgradeParams.Type; - readonly "plugin/list": typeof CodexSchema.V2PluginListParams.Type; - readonly "plugin/read": typeof CodexSchema.V2PluginReadParams.Type; - readonly "plugin/skill/read": typeof CodexSchema.V2PluginSkillReadParams.Type; - readonly "plugin/share/save": typeof CodexSchema.V2PluginShareSaveParams.Type; - readonly "plugin/share/updateTargets": typeof CodexSchema.V2PluginShareUpdateTargetsParams.Type; - readonly "plugin/share/list": typeof CodexSchema.V2PluginShareListParams.Type; - readonly "plugin/share/delete": typeof CodexSchema.V2PluginShareDeleteParams.Type; - readonly "app/list": typeof CodexSchema.V2AppsListParams.Type; - readonly "fs/readFile": typeof CodexSchema.V2FsReadFileParams.Type; - readonly "fs/writeFile": typeof CodexSchema.V2FsWriteFileParams.Type; - readonly "fs/createDirectory": typeof CodexSchema.V2FsCreateDirectoryParams.Type; - readonly "fs/getMetadata": typeof CodexSchema.V2FsGetMetadataParams.Type; - readonly "fs/readDirectory": typeof CodexSchema.V2FsReadDirectoryParams.Type; - readonly "fs/remove": typeof CodexSchema.V2FsRemoveParams.Type; - readonly "fs/copy": typeof CodexSchema.V2FsCopyParams.Type; - readonly "fs/watch": typeof CodexSchema.V2FsWatchParams.Type; - readonly "fs/unwatch": typeof CodexSchema.V2FsUnwatchParams.Type; - readonly "skills/config/write": typeof CodexSchema.V2SkillsConfigWriteParams.Type; - readonly "plugin/install": typeof CodexSchema.V2PluginInstallParams.Type; - readonly "plugin/uninstall": typeof CodexSchema.V2PluginUninstallParams.Type; - readonly "turn/start": typeof CodexSchema.V2TurnStartParams.Type; - readonly "turn/steer": typeof CodexSchema.V2TurnSteerParams.Type; - readonly "turn/interrupt": typeof CodexSchema.V2TurnInterruptParams.Type; - readonly "review/start": typeof CodexSchema.V2ReviewStartParams.Type; - readonly "model/list": typeof CodexSchema.V2ModelListParams.Type; - readonly "modelProvider/capabilities/read": typeof CodexSchema.V2ModelProviderCapabilitiesReadParams.Type; - readonly "experimentalFeature/list": typeof CodexSchema.V2ExperimentalFeatureListParams.Type; - readonly "experimentalFeature/enablement/set": typeof CodexSchema.V2ExperimentalFeatureEnablementSetParams.Type; - readonly "mcpServer/oauth/login": typeof CodexSchema.V2McpServerOauthLoginParams.Type; + readonly initialize: CodexSchema.V1InitializeParams; + readonly "thread/start": CodexSchema.V2ThreadStartParams; + readonly "thread/resume": CodexSchema.V2ThreadResumeParams; + readonly "thread/fork": CodexSchema.V2ThreadForkParams; + readonly "thread/archive": CodexSchema.V2ThreadArchiveParams; + readonly "thread/unsubscribe": CodexSchema.V2ThreadUnsubscribeParams; + readonly "thread/name/set": CodexSchema.V2ThreadSetNameParams; + readonly "thread/metadata/update": CodexSchema.V2ThreadMetadataUpdateParams; + readonly "thread/unarchive": CodexSchema.V2ThreadUnarchiveParams; + readonly "thread/compact/start": CodexSchema.V2ThreadCompactStartParams; + readonly "thread/shellCommand": CodexSchema.V2ThreadShellCommandParams; + readonly "thread/approveGuardianDeniedAction": CodexSchema.V2ThreadApproveGuardianDeniedActionParams; + readonly "thread/rollback": CodexSchema.V2ThreadRollbackParams; + readonly "thread/list": CodexSchema.V2ThreadListParams; + readonly "thread/loaded/list": CodexSchema.V2ThreadLoadedListParams; + readonly "thread/read": CodexSchema.V2ThreadReadParams; + readonly "thread/inject_items": CodexSchema.V2ThreadInjectItemsParams; + readonly "skills/list": CodexSchema.V2SkillsListParams; + readonly "hooks/list": CodexSchema.V2HooksListParams; + readonly "marketplace/add": CodexSchema.V2MarketplaceAddParams; + readonly "marketplace/remove": CodexSchema.V2MarketplaceRemoveParams; + readonly "marketplace/upgrade": CodexSchema.V2MarketplaceUpgradeParams; + readonly "plugin/list": CodexSchema.V2PluginListParams; + readonly "plugin/read": CodexSchema.V2PluginReadParams; + readonly "plugin/skill/read": CodexSchema.V2PluginSkillReadParams; + readonly "plugin/share/save": CodexSchema.V2PluginShareSaveParams; + readonly "plugin/share/updateTargets": CodexSchema.V2PluginShareUpdateTargetsParams; + readonly "plugin/share/list": CodexSchema.V2PluginShareListParams; + readonly "plugin/share/delete": CodexSchema.V2PluginShareDeleteParams; + readonly "app/list": CodexSchema.V2AppsListParams; + readonly "fs/readFile": CodexSchema.V2FsReadFileParams; + readonly "fs/writeFile": CodexSchema.V2FsWriteFileParams; + readonly "fs/createDirectory": CodexSchema.V2FsCreateDirectoryParams; + readonly "fs/getMetadata": CodexSchema.V2FsGetMetadataParams; + readonly "fs/readDirectory": CodexSchema.V2FsReadDirectoryParams; + readonly "fs/remove": CodexSchema.V2FsRemoveParams; + readonly "fs/copy": CodexSchema.V2FsCopyParams; + readonly "fs/watch": CodexSchema.V2FsWatchParams; + readonly "fs/unwatch": CodexSchema.V2FsUnwatchParams; + readonly "skills/config/write": CodexSchema.V2SkillsConfigWriteParams; + readonly "plugin/install": CodexSchema.V2PluginInstallParams; + readonly "plugin/uninstall": CodexSchema.V2PluginUninstallParams; + readonly "turn/start": CodexSchema.V2TurnStartParams; + readonly "turn/steer": CodexSchema.V2TurnSteerParams; + readonly "turn/interrupt": CodexSchema.V2TurnInterruptParams; + readonly "review/start": CodexSchema.V2ReviewStartParams; + readonly "model/list": CodexSchema.V2ModelListParams; + readonly "modelProvider/capabilities/read": CodexSchema.V2ModelProviderCapabilitiesReadParams; + readonly "experimentalFeature/list": CodexSchema.V2ExperimentalFeatureListParams; + readonly "experimentalFeature/enablement/set": CodexSchema.V2ExperimentalFeatureEnablementSetParams; + readonly "mcpServer/oauth/login": CodexSchema.V2McpServerOauthLoginParams; readonly "config/mcpServer/reload": undefined; - readonly "mcpServerStatus/list": typeof CodexSchema.V2ListMcpServerStatusParams.Type; - readonly "mcpServer/resource/read": typeof CodexSchema.V2McpResourceReadParams.Type; - readonly "mcpServer/tool/call": typeof CodexSchema.V2McpServerToolCallParams.Type; - readonly "windowsSandbox/setupStart": typeof CodexSchema.V2WindowsSandboxSetupStartParams.Type; + readonly "mcpServerStatus/list": CodexSchema.V2ListMcpServerStatusParams; + readonly "mcpServer/resource/read": CodexSchema.V2McpResourceReadParams; + readonly "mcpServer/tool/call": CodexSchema.V2McpServerToolCallParams; + readonly "windowsSandbox/setupStart": CodexSchema.V2WindowsSandboxSetupStartParams; readonly "windowsSandbox/readiness": undefined; - readonly "account/login/start": typeof CodexSchema.V2LoginAccountParams.Type; - readonly "account/login/cancel": typeof CodexSchema.V2CancelLoginAccountParams.Type; + readonly "account/login/start": CodexSchema.V2LoginAccountParams; + readonly "account/login/cancel": CodexSchema.V2CancelLoginAccountParams; readonly "account/logout": undefined; readonly "account/rateLimits/read": undefined; - readonly "account/sendAddCreditsNudgeEmail": typeof CodexSchema.V2SendAddCreditsNudgeEmailParams.Type; - readonly "feedback/upload": typeof CodexSchema.V2FeedbackUploadParams.Type; - readonly "command/exec": typeof CodexSchema.V2CommandExecParams.Type; - readonly "command/exec/write": typeof CodexSchema.V2CommandExecWriteParams.Type; - readonly "command/exec/terminate": typeof CodexSchema.V2CommandExecTerminateParams.Type; - readonly "command/exec/resize": typeof CodexSchema.V2CommandExecResizeParams.Type; - readonly "config/read": typeof CodexSchema.V2ConfigReadParams.Type; - readonly "externalAgentConfig/detect": typeof CodexSchema.V2ExternalAgentConfigDetectParams.Type; - readonly "externalAgentConfig/import": typeof CodexSchema.V2ExternalAgentConfigImportParams.Type; - readonly "config/value/write": typeof CodexSchema.V2ConfigValueWriteParams.Type; - readonly "config/batchWrite": typeof CodexSchema.V2ConfigBatchWriteParams.Type; + readonly "account/sendAddCreditsNudgeEmail": CodexSchema.V2SendAddCreditsNudgeEmailParams; + readonly "feedback/upload": CodexSchema.V2FeedbackUploadParams; + readonly "command/exec": CodexSchema.V2CommandExecParams; + readonly "command/exec/write": CodexSchema.V2CommandExecWriteParams; + readonly "command/exec/terminate": CodexSchema.V2CommandExecTerminateParams; + readonly "command/exec/resize": CodexSchema.V2CommandExecResizeParams; + readonly "config/read": CodexSchema.V2ConfigReadParams; + readonly "externalAgentConfig/detect": CodexSchema.V2ExternalAgentConfigDetectParams; + readonly "externalAgentConfig/import": CodexSchema.V2ExternalAgentConfigImportParams; + readonly "config/value/write": CodexSchema.V2ConfigValueWriteParams; + readonly "config/batchWrite": CodexSchema.V2ConfigBatchWriteParams; readonly "configRequirements/read": undefined; - readonly "account/read": typeof CodexSchema.V2GetAccountParams.Type; - readonly getConversationSummary: typeof CodexSchema.GetConversationSummaryParams.Type; - readonly gitDiffToRemote: typeof CodexSchema.GitDiffToRemoteParams.Type; - readonly getAuthStatus: typeof CodexSchema.GetAuthStatusParams.Type; - readonly fuzzyFileSearch: typeof CodexSchema.FuzzyFileSearchParams.Type; + readonly "account/read": CodexSchema.V2GetAccountParams; + readonly getConversationSummary: CodexSchema.GetConversationSummaryParams; + readonly gitDiffToRemote: CodexSchema.GitDiffToRemoteParams; + readonly getAuthStatus: CodexSchema.GetAuthStatusParams; + readonly fuzzyFileSearch: CodexSchema.FuzzyFileSearchParams; } export interface ClientRequestResponsesByMethod { - readonly initialize: typeof CodexSchema.V1InitializeResponse.Type; - readonly "thread/start": typeof CodexSchema.V2ThreadStartResponse.Type; - readonly "thread/resume": typeof CodexSchema.V2ThreadResumeResponse.Type; - readonly "thread/fork": typeof CodexSchema.V2ThreadForkResponse.Type; - readonly "thread/archive": typeof CodexSchema.V2ThreadArchiveResponse.Type; - readonly "thread/unsubscribe": typeof CodexSchema.V2ThreadUnsubscribeResponse.Type; - readonly "thread/name/set": typeof CodexSchema.V2ThreadSetNameResponse.Type; - readonly "thread/metadata/update": typeof CodexSchema.V2ThreadMetadataUpdateResponse.Type; - readonly "thread/unarchive": typeof CodexSchema.V2ThreadUnarchiveResponse.Type; - readonly "thread/compact/start": typeof CodexSchema.V2ThreadCompactStartResponse.Type; - readonly "thread/shellCommand": typeof CodexSchema.V2ThreadShellCommandResponse.Type; - readonly "thread/approveGuardianDeniedAction": typeof CodexSchema.V2ThreadApproveGuardianDeniedActionResponse.Type; - readonly "thread/rollback": typeof CodexSchema.V2ThreadRollbackResponse.Type; - readonly "thread/list": typeof CodexSchema.V2ThreadListResponse.Type; - readonly "thread/loaded/list": typeof CodexSchema.V2ThreadLoadedListResponse.Type; - readonly "thread/read": typeof CodexSchema.V2ThreadReadResponse.Type; - readonly "thread/inject_items": typeof CodexSchema.V2ThreadInjectItemsResponse.Type; - readonly "skills/list": typeof CodexSchema.V2SkillsListResponse.Type; - readonly "hooks/list": typeof CodexSchema.V2HooksListResponse.Type; - readonly "marketplace/add": typeof CodexSchema.V2MarketplaceAddResponse.Type; - readonly "marketplace/remove": typeof CodexSchema.V2MarketplaceRemoveResponse.Type; - readonly "marketplace/upgrade": typeof CodexSchema.V2MarketplaceUpgradeResponse.Type; - readonly "plugin/list": typeof CodexSchema.V2PluginListResponse.Type; - readonly "plugin/read": typeof CodexSchema.V2PluginReadResponse.Type; - readonly "plugin/skill/read": typeof CodexSchema.V2PluginSkillReadResponse.Type; - readonly "plugin/share/save": typeof CodexSchema.V2PluginShareSaveResponse.Type; - readonly "plugin/share/updateTargets": typeof CodexSchema.V2PluginShareUpdateTargetsResponse.Type; - readonly "plugin/share/list": typeof CodexSchema.V2PluginShareListResponse.Type; - readonly "plugin/share/delete": typeof CodexSchema.V2PluginShareDeleteResponse.Type; - readonly "app/list": typeof CodexSchema.V2AppsListResponse.Type; - readonly "fs/readFile": typeof CodexSchema.V2FsReadFileResponse.Type; - readonly "fs/writeFile": typeof CodexSchema.V2FsWriteFileResponse.Type; - readonly "fs/createDirectory": typeof CodexSchema.V2FsCreateDirectoryResponse.Type; - readonly "fs/getMetadata": typeof CodexSchema.V2FsGetMetadataResponse.Type; - readonly "fs/readDirectory": typeof CodexSchema.V2FsReadDirectoryResponse.Type; - readonly "fs/remove": typeof CodexSchema.V2FsRemoveResponse.Type; - readonly "fs/copy": typeof CodexSchema.V2FsCopyResponse.Type; - readonly "fs/watch": typeof CodexSchema.V2FsWatchResponse.Type; - readonly "fs/unwatch": typeof CodexSchema.V2FsUnwatchResponse.Type; - readonly "skills/config/write": typeof CodexSchema.V2SkillsConfigWriteResponse.Type; - readonly "plugin/install": typeof CodexSchema.V2PluginInstallResponse.Type; - readonly "plugin/uninstall": typeof CodexSchema.V2PluginUninstallResponse.Type; - readonly "turn/start": typeof CodexSchema.V2TurnStartResponse.Type; - readonly "turn/steer": typeof CodexSchema.V2TurnSteerResponse.Type; - readonly "turn/interrupt": typeof CodexSchema.V2TurnInterruptResponse.Type; - readonly "review/start": typeof CodexSchema.V2ReviewStartResponse.Type; - readonly "model/list": typeof CodexSchema.V2ModelListResponse.Type; - readonly "modelProvider/capabilities/read": typeof CodexSchema.V2ModelProviderCapabilitiesReadResponse.Type; - readonly "experimentalFeature/list": typeof CodexSchema.V2ExperimentalFeatureListResponse.Type; - readonly "experimentalFeature/enablement/set": typeof CodexSchema.V2ExperimentalFeatureEnablementSetResponse.Type; - readonly "mcpServer/oauth/login": typeof CodexSchema.V2McpServerOauthLoginResponse.Type; - readonly "config/mcpServer/reload": typeof CodexSchema.V2McpServerRefreshResponse.Type; - readonly "mcpServerStatus/list": typeof CodexSchema.V2ListMcpServerStatusResponse.Type; - readonly "mcpServer/resource/read": typeof CodexSchema.V2McpResourceReadResponse.Type; - readonly "mcpServer/tool/call": typeof CodexSchema.V2McpServerToolCallResponse.Type; - readonly "windowsSandbox/setupStart": typeof CodexSchema.V2WindowsSandboxSetupStartResponse.Type; - readonly "windowsSandbox/readiness": typeof CodexSchema.V2WindowsSandboxReadinessResponse.Type; - readonly "account/login/start": typeof CodexSchema.V2LoginAccountResponse.Type; - readonly "account/login/cancel": typeof CodexSchema.V2CancelLoginAccountResponse.Type; - readonly "account/logout": typeof CodexSchema.V2LogoutAccountResponse.Type; - readonly "account/rateLimits/read": typeof CodexSchema.V2GetAccountRateLimitsResponse.Type; - readonly "account/sendAddCreditsNudgeEmail": typeof CodexSchema.V2SendAddCreditsNudgeEmailResponse.Type; - readonly "feedback/upload": typeof CodexSchema.V2FeedbackUploadResponse.Type; - readonly "command/exec": typeof CodexSchema.V2CommandExecResponse.Type; - readonly "command/exec/write": typeof CodexSchema.V2CommandExecWriteResponse.Type; - readonly "command/exec/terminate": typeof CodexSchema.V2CommandExecTerminateResponse.Type; - readonly "command/exec/resize": typeof CodexSchema.V2CommandExecResizeResponse.Type; - readonly "config/read": typeof CodexSchema.V2ConfigReadResponse.Type; - readonly "externalAgentConfig/detect": typeof CodexSchema.V2ExternalAgentConfigDetectResponse.Type; - readonly "externalAgentConfig/import": typeof CodexSchema.V2ExternalAgentConfigImportResponse.Type; - readonly "config/value/write": typeof CodexSchema.V2ConfigWriteResponse.Type; - readonly "config/batchWrite": typeof CodexSchema.V2ConfigWriteResponse.Type; - readonly "configRequirements/read": typeof CodexSchema.V2ConfigRequirementsReadResponse.Type; - readonly "account/read": typeof CodexSchema.V2GetAccountResponse.Type; - readonly getConversationSummary: typeof CodexSchema.GetConversationSummaryResponse.Type; - readonly gitDiffToRemote: typeof CodexSchema.GitDiffToRemoteResponse.Type; - readonly getAuthStatus: typeof CodexSchema.GetAuthStatusResponse.Type; - readonly fuzzyFileSearch: typeof CodexSchema.FuzzyFileSearchResponse.Type; + readonly initialize: CodexSchema.V1InitializeResponse; + readonly "thread/start": CodexSchema.V2ThreadStartResponse; + readonly "thread/resume": CodexSchema.V2ThreadResumeResponse; + readonly "thread/fork": CodexSchema.V2ThreadForkResponse; + readonly "thread/archive": CodexSchema.V2ThreadArchiveResponse; + readonly "thread/unsubscribe": CodexSchema.V2ThreadUnsubscribeResponse; + readonly "thread/name/set": CodexSchema.V2ThreadSetNameResponse; + readonly "thread/metadata/update": CodexSchema.V2ThreadMetadataUpdateResponse; + readonly "thread/unarchive": CodexSchema.V2ThreadUnarchiveResponse; + readonly "thread/compact/start": CodexSchema.V2ThreadCompactStartResponse; + readonly "thread/shellCommand": CodexSchema.V2ThreadShellCommandResponse; + readonly "thread/approveGuardianDeniedAction": CodexSchema.V2ThreadApproveGuardianDeniedActionResponse; + readonly "thread/rollback": CodexSchema.V2ThreadRollbackResponse; + readonly "thread/list": CodexSchema.V2ThreadListResponse; + readonly "thread/loaded/list": CodexSchema.V2ThreadLoadedListResponse; + readonly "thread/read": CodexSchema.V2ThreadReadResponse; + readonly "thread/inject_items": CodexSchema.V2ThreadInjectItemsResponse; + readonly "skills/list": CodexSchema.V2SkillsListResponse; + readonly "hooks/list": CodexSchema.V2HooksListResponse; + readonly "marketplace/add": CodexSchema.V2MarketplaceAddResponse; + readonly "marketplace/remove": CodexSchema.V2MarketplaceRemoveResponse; + readonly "marketplace/upgrade": CodexSchema.V2MarketplaceUpgradeResponse; + readonly "plugin/list": CodexSchema.V2PluginListResponse; + readonly "plugin/read": CodexSchema.V2PluginReadResponse; + readonly "plugin/skill/read": CodexSchema.V2PluginSkillReadResponse; + readonly "plugin/share/save": CodexSchema.V2PluginShareSaveResponse; + readonly "plugin/share/updateTargets": CodexSchema.V2PluginShareUpdateTargetsResponse; + readonly "plugin/share/list": CodexSchema.V2PluginShareListResponse; + readonly "plugin/share/delete": CodexSchema.V2PluginShareDeleteResponse; + readonly "app/list": CodexSchema.V2AppsListResponse; + readonly "fs/readFile": CodexSchema.V2FsReadFileResponse; + readonly "fs/writeFile": CodexSchema.V2FsWriteFileResponse; + readonly "fs/createDirectory": CodexSchema.V2FsCreateDirectoryResponse; + readonly "fs/getMetadata": CodexSchema.V2FsGetMetadataResponse; + readonly "fs/readDirectory": CodexSchema.V2FsReadDirectoryResponse; + readonly "fs/remove": CodexSchema.V2FsRemoveResponse; + readonly "fs/copy": CodexSchema.V2FsCopyResponse; + readonly "fs/watch": CodexSchema.V2FsWatchResponse; + readonly "fs/unwatch": CodexSchema.V2FsUnwatchResponse; + readonly "skills/config/write": CodexSchema.V2SkillsConfigWriteResponse; + readonly "plugin/install": CodexSchema.V2PluginInstallResponse; + readonly "plugin/uninstall": CodexSchema.V2PluginUninstallResponse; + readonly "turn/start": CodexSchema.V2TurnStartResponse; + readonly "turn/steer": CodexSchema.V2TurnSteerResponse; + readonly "turn/interrupt": CodexSchema.V2TurnInterruptResponse; + readonly "review/start": CodexSchema.V2ReviewStartResponse; + readonly "model/list": CodexSchema.V2ModelListResponse; + readonly "modelProvider/capabilities/read": CodexSchema.V2ModelProviderCapabilitiesReadResponse; + readonly "experimentalFeature/list": CodexSchema.V2ExperimentalFeatureListResponse; + readonly "experimentalFeature/enablement/set": CodexSchema.V2ExperimentalFeatureEnablementSetResponse; + readonly "mcpServer/oauth/login": CodexSchema.V2McpServerOauthLoginResponse; + readonly "config/mcpServer/reload": CodexSchema.V2McpServerRefreshResponse; + readonly "mcpServerStatus/list": CodexSchema.V2ListMcpServerStatusResponse; + readonly "mcpServer/resource/read": CodexSchema.V2McpResourceReadResponse; + readonly "mcpServer/tool/call": CodexSchema.V2McpServerToolCallResponse; + readonly "windowsSandbox/setupStart": CodexSchema.V2WindowsSandboxSetupStartResponse; + readonly "windowsSandbox/readiness": CodexSchema.V2WindowsSandboxReadinessResponse; + readonly "account/login/start": CodexSchema.V2LoginAccountResponse; + readonly "account/login/cancel": CodexSchema.V2CancelLoginAccountResponse; + readonly "account/logout": CodexSchema.V2LogoutAccountResponse; + readonly "account/rateLimits/read": CodexSchema.V2GetAccountRateLimitsResponse; + readonly "account/sendAddCreditsNudgeEmail": CodexSchema.V2SendAddCreditsNudgeEmailResponse; + readonly "feedback/upload": CodexSchema.V2FeedbackUploadResponse; + readonly "command/exec": CodexSchema.V2CommandExecResponse; + readonly "command/exec/write": CodexSchema.V2CommandExecWriteResponse; + readonly "command/exec/terminate": CodexSchema.V2CommandExecTerminateResponse; + readonly "command/exec/resize": CodexSchema.V2CommandExecResizeResponse; + readonly "config/read": CodexSchema.V2ConfigReadResponse; + readonly "externalAgentConfig/detect": CodexSchema.V2ExternalAgentConfigDetectResponse; + readonly "externalAgentConfig/import": CodexSchema.V2ExternalAgentConfigImportResponse; + readonly "config/value/write": CodexSchema.V2ConfigWriteResponse; + readonly "config/batchWrite": CodexSchema.V2ConfigWriteResponse; + readonly "configRequirements/read": CodexSchema.V2ConfigRequirementsReadResponse; + readonly "account/read": CodexSchema.V2GetAccountResponse; + readonly getConversationSummary: CodexSchema.GetConversationSummaryResponse; + readonly gitDiffToRemote: CodexSchema.GitDiffToRemoteResponse; + readonly getAuthStatus: CodexSchema.GetAuthStatusResponse; + readonly fuzzyFileSearch: CodexSchema.FuzzyFileSearchResponse; } export interface ClientNotificationParamsByMethod { @@ -339,94 +339,94 @@ export interface ClientNotificationParamsByMethod { } export interface ServerRequestParamsByMethod { - readonly "item/commandExecution/requestApproval": typeof CodexSchema.CommandExecutionRequestApprovalParams.Type; - readonly "item/fileChange/requestApproval": typeof CodexSchema.FileChangeRequestApprovalParams.Type; - readonly "item/tool/requestUserInput": typeof CodexSchema.ToolRequestUserInputParams.Type; - readonly "mcpServer/elicitation/request": typeof CodexSchema.McpServerElicitationRequestParams.Type; - readonly "item/permissions/requestApproval": typeof CodexSchema.PermissionsRequestApprovalParams.Type; - readonly "item/tool/call": typeof CodexSchema.DynamicToolCallParams.Type; - readonly "account/chatgptAuthTokens/refresh": typeof CodexSchema.ChatgptAuthTokensRefreshParams.Type; - readonly applyPatchApproval: typeof CodexSchema.ApplyPatchApprovalParams.Type; - readonly execCommandApproval: typeof CodexSchema.ExecCommandApprovalParams.Type; + readonly "item/commandExecution/requestApproval": CodexSchema.CommandExecutionRequestApprovalParams; + readonly "item/fileChange/requestApproval": CodexSchema.FileChangeRequestApprovalParams; + readonly "item/tool/requestUserInput": CodexSchema.ToolRequestUserInputParams; + readonly "mcpServer/elicitation/request": CodexSchema.McpServerElicitationRequestParams; + readonly "item/permissions/requestApproval": CodexSchema.PermissionsRequestApprovalParams; + readonly "item/tool/call": CodexSchema.DynamicToolCallParams; + readonly "account/chatgptAuthTokens/refresh": CodexSchema.ChatgptAuthTokensRefreshParams; + readonly applyPatchApproval: CodexSchema.ApplyPatchApprovalParams; + readonly execCommandApproval: CodexSchema.ExecCommandApprovalParams; } export interface ServerRequestResponsesByMethod { - readonly "item/commandExecution/requestApproval": typeof CodexSchema.CommandExecutionRequestApprovalResponse.Type; - readonly "item/fileChange/requestApproval": typeof CodexSchema.FileChangeRequestApprovalResponse.Type; - readonly "item/tool/requestUserInput": typeof CodexSchema.ToolRequestUserInputResponse.Type; - readonly "mcpServer/elicitation/request": typeof CodexSchema.McpServerElicitationRequestResponse.Type; - readonly "item/permissions/requestApproval": typeof CodexSchema.PermissionsRequestApprovalResponse.Type; - readonly "item/tool/call": typeof CodexSchema.DynamicToolCallResponse.Type; - readonly "account/chatgptAuthTokens/refresh": typeof CodexSchema.ChatgptAuthTokensRefreshResponse.Type; - readonly applyPatchApproval: typeof CodexSchema.ApplyPatchApprovalResponse.Type; - readonly execCommandApproval: typeof CodexSchema.ExecCommandApprovalResponse.Type; + readonly "item/commandExecution/requestApproval": CodexSchema.CommandExecutionRequestApprovalResponse; + readonly "item/fileChange/requestApproval": CodexSchema.FileChangeRequestApprovalResponse; + readonly "item/tool/requestUserInput": CodexSchema.ToolRequestUserInputResponse; + readonly "mcpServer/elicitation/request": CodexSchema.McpServerElicitationRequestResponse; + readonly "item/permissions/requestApproval": CodexSchema.PermissionsRequestApprovalResponse; + readonly "item/tool/call": CodexSchema.DynamicToolCallResponse; + readonly "account/chatgptAuthTokens/refresh": CodexSchema.ChatgptAuthTokensRefreshResponse; + readonly applyPatchApproval: CodexSchema.ApplyPatchApprovalResponse; + readonly execCommandApproval: CodexSchema.ExecCommandApprovalResponse; } export interface ServerNotificationParamsByMethod { - readonly error: typeof CodexSchema.V2ErrorNotification.Type; - readonly "thread/started": typeof CodexSchema.V2ThreadStartedNotification.Type; - readonly "thread/status/changed": typeof CodexSchema.V2ThreadStatusChangedNotification.Type; - readonly "thread/archived": typeof CodexSchema.V2ThreadArchivedNotification.Type; - readonly "thread/unarchived": typeof CodexSchema.V2ThreadUnarchivedNotification.Type; - readonly "thread/closed": typeof CodexSchema.V2ThreadClosedNotification.Type; - readonly "skills/changed": typeof CodexSchema.V2SkillsChangedNotification.Type; - readonly "thread/name/updated": typeof CodexSchema.V2ThreadNameUpdatedNotification.Type; - readonly "thread/goal/updated": typeof CodexSchema.V2ThreadGoalUpdatedNotification.Type; - readonly "thread/goal/cleared": typeof CodexSchema.V2ThreadGoalClearedNotification.Type; - readonly "thread/tokenUsage/updated": typeof CodexSchema.V2ThreadTokenUsageUpdatedNotification.Type; - readonly "turn/started": typeof CodexSchema.V2TurnStartedNotification.Type; - readonly "hook/started": typeof CodexSchema.V2HookStartedNotification.Type; - readonly "turn/completed": typeof CodexSchema.V2TurnCompletedNotification.Type; - readonly "hook/completed": typeof CodexSchema.V2HookCompletedNotification.Type; - readonly "turn/diff/updated": typeof CodexSchema.V2TurnDiffUpdatedNotification.Type; - readonly "turn/plan/updated": typeof CodexSchema.V2TurnPlanUpdatedNotification.Type; - readonly "item/started": typeof CodexSchema.V2ItemStartedNotification.Type; - readonly "item/autoApprovalReview/started": typeof CodexSchema.V2ItemGuardianApprovalReviewStartedNotification.Type; - readonly "item/autoApprovalReview/completed": typeof CodexSchema.V2ItemGuardianApprovalReviewCompletedNotification.Type; - readonly "item/completed": typeof CodexSchema.V2ItemCompletedNotification.Type; - readonly "rawResponseItem/completed": typeof CodexSchema.V2RawResponseItemCompletedNotification.Type; - readonly "item/agentMessage/delta": typeof CodexSchema.V2AgentMessageDeltaNotification.Type; - readonly "item/plan/delta": typeof CodexSchema.V2PlanDeltaNotification.Type; - readonly "command/exec/outputDelta": typeof CodexSchema.V2CommandExecOutputDeltaNotification.Type; - readonly "process/outputDelta": typeof CodexSchema.V2ProcessOutputDeltaNotification.Type; - readonly "process/exited": typeof CodexSchema.V2ProcessExitedNotification.Type; - readonly "item/commandExecution/outputDelta": typeof CodexSchema.V2CommandExecutionOutputDeltaNotification.Type; - readonly "item/commandExecution/terminalInteraction": typeof CodexSchema.V2TerminalInteractionNotification.Type; - readonly "item/fileChange/outputDelta": typeof CodexSchema.V2FileChangeOutputDeltaNotification.Type; - readonly "item/fileChange/patchUpdated": typeof CodexSchema.V2FileChangePatchUpdatedNotification.Type; - readonly "serverRequest/resolved": typeof CodexSchema.V2ServerRequestResolvedNotification.Type; - readonly "item/mcpToolCall/progress": typeof CodexSchema.V2McpToolCallProgressNotification.Type; - readonly "mcpServer/oauthLogin/completed": typeof CodexSchema.V2McpServerOauthLoginCompletedNotification.Type; - readonly "mcpServer/startupStatus/updated": typeof CodexSchema.V2McpServerStatusUpdatedNotification.Type; - readonly "account/updated": typeof CodexSchema.V2AccountUpdatedNotification.Type; - readonly "account/rateLimits/updated": typeof CodexSchema.V2AccountRateLimitsUpdatedNotification.Type; - readonly "app/list/updated": typeof CodexSchema.V2AppListUpdatedNotification.Type; - readonly "remoteControl/status/changed": typeof CodexSchema.V2RemoteControlStatusChangedNotification.Type; - readonly "externalAgentConfig/import/completed": typeof CodexSchema.V2ExternalAgentConfigImportCompletedNotification.Type; - readonly "fs/changed": typeof CodexSchema.V2FsChangedNotification.Type; - readonly "item/reasoning/summaryTextDelta": typeof CodexSchema.V2ReasoningSummaryTextDeltaNotification.Type; - readonly "item/reasoning/summaryPartAdded": typeof CodexSchema.V2ReasoningSummaryPartAddedNotification.Type; - readonly "item/reasoning/textDelta": typeof CodexSchema.V2ReasoningTextDeltaNotification.Type; - readonly "thread/compacted": typeof CodexSchema.V2ContextCompactedNotification.Type; - readonly "model/rerouted": typeof CodexSchema.V2ModelReroutedNotification.Type; - readonly "model/verification": typeof CodexSchema.V2ModelVerificationNotification.Type; - readonly warning: typeof CodexSchema.V2WarningNotification.Type; - readonly guardianWarning: typeof CodexSchema.V2GuardianWarningNotification.Type; - readonly deprecationNotice: typeof CodexSchema.V2DeprecationNoticeNotification.Type; - readonly configWarning: typeof CodexSchema.V2ConfigWarningNotification.Type; - readonly "fuzzyFileSearch/sessionUpdated": typeof CodexSchema.FuzzyFileSearchSessionUpdatedNotification.Type; - readonly "fuzzyFileSearch/sessionCompleted": typeof CodexSchema.FuzzyFileSearchSessionCompletedNotification.Type; - readonly "thread/realtime/started": typeof CodexSchema.V2ThreadRealtimeStartedNotification.Type; - readonly "thread/realtime/itemAdded": typeof CodexSchema.V2ThreadRealtimeItemAddedNotification.Type; - readonly "thread/realtime/transcript/delta": typeof CodexSchema.V2ThreadRealtimeTranscriptDeltaNotification.Type; - readonly "thread/realtime/transcript/done": typeof CodexSchema.V2ThreadRealtimeTranscriptDoneNotification.Type; - readonly "thread/realtime/outputAudio/delta": typeof CodexSchema.V2ThreadRealtimeOutputAudioDeltaNotification.Type; - readonly "thread/realtime/sdp": typeof CodexSchema.V2ThreadRealtimeSdpNotification.Type; - readonly "thread/realtime/error": typeof CodexSchema.V2ThreadRealtimeErrorNotification.Type; - readonly "thread/realtime/closed": typeof CodexSchema.V2ThreadRealtimeClosedNotification.Type; - readonly "windows/worldWritableWarning": typeof CodexSchema.V2WindowsWorldWritableWarningNotification.Type; - readonly "windowsSandbox/setupCompleted": typeof CodexSchema.V2WindowsSandboxSetupCompletedNotification.Type; - readonly "account/login/completed": typeof CodexSchema.V2AccountLoginCompletedNotification.Type; + readonly error: CodexSchema.V2ErrorNotification; + readonly "thread/started": CodexSchema.V2ThreadStartedNotification; + readonly "thread/status/changed": CodexSchema.V2ThreadStatusChangedNotification; + readonly "thread/archived": CodexSchema.V2ThreadArchivedNotification; + readonly "thread/unarchived": CodexSchema.V2ThreadUnarchivedNotification; + readonly "thread/closed": CodexSchema.V2ThreadClosedNotification; + readonly "skills/changed": CodexSchema.V2SkillsChangedNotification; + readonly "thread/name/updated": CodexSchema.V2ThreadNameUpdatedNotification; + readonly "thread/goal/updated": CodexSchema.V2ThreadGoalUpdatedNotification; + readonly "thread/goal/cleared": CodexSchema.V2ThreadGoalClearedNotification; + readonly "thread/tokenUsage/updated": CodexSchema.V2ThreadTokenUsageUpdatedNotification; + readonly "turn/started": CodexSchema.V2TurnStartedNotification; + readonly "hook/started": CodexSchema.V2HookStartedNotification; + readonly "turn/completed": CodexSchema.V2TurnCompletedNotification; + readonly "hook/completed": CodexSchema.V2HookCompletedNotification; + readonly "turn/diff/updated": CodexSchema.V2TurnDiffUpdatedNotification; + readonly "turn/plan/updated": CodexSchema.V2TurnPlanUpdatedNotification; + readonly "item/started": CodexSchema.V2ItemStartedNotification; + readonly "item/autoApprovalReview/started": CodexSchema.V2ItemGuardianApprovalReviewStartedNotification; + readonly "item/autoApprovalReview/completed": CodexSchema.V2ItemGuardianApprovalReviewCompletedNotification; + readonly "item/completed": CodexSchema.V2ItemCompletedNotification; + readonly "rawResponseItem/completed": CodexSchema.V2RawResponseItemCompletedNotification; + readonly "item/agentMessage/delta": CodexSchema.V2AgentMessageDeltaNotification; + readonly "item/plan/delta": CodexSchema.V2PlanDeltaNotification; + readonly "command/exec/outputDelta": CodexSchema.V2CommandExecOutputDeltaNotification; + readonly "process/outputDelta": CodexSchema.V2ProcessOutputDeltaNotification; + readonly "process/exited": CodexSchema.V2ProcessExitedNotification; + readonly "item/commandExecution/outputDelta": CodexSchema.V2CommandExecutionOutputDeltaNotification; + readonly "item/commandExecution/terminalInteraction": CodexSchema.V2TerminalInteractionNotification; + readonly "item/fileChange/outputDelta": CodexSchema.V2FileChangeOutputDeltaNotification; + readonly "item/fileChange/patchUpdated": CodexSchema.V2FileChangePatchUpdatedNotification; + readonly "serverRequest/resolved": CodexSchema.V2ServerRequestResolvedNotification; + readonly "item/mcpToolCall/progress": CodexSchema.V2McpToolCallProgressNotification; + readonly "mcpServer/oauthLogin/completed": CodexSchema.V2McpServerOauthLoginCompletedNotification; + readonly "mcpServer/startupStatus/updated": CodexSchema.V2McpServerStatusUpdatedNotification; + readonly "account/updated": CodexSchema.V2AccountUpdatedNotification; + readonly "account/rateLimits/updated": CodexSchema.V2AccountRateLimitsUpdatedNotification; + readonly "app/list/updated": CodexSchema.V2AppListUpdatedNotification; + readonly "remoteControl/status/changed": CodexSchema.V2RemoteControlStatusChangedNotification; + readonly "externalAgentConfig/import/completed": CodexSchema.V2ExternalAgentConfigImportCompletedNotification; + readonly "fs/changed": CodexSchema.V2FsChangedNotification; + readonly "item/reasoning/summaryTextDelta": CodexSchema.V2ReasoningSummaryTextDeltaNotification; + readonly "item/reasoning/summaryPartAdded": CodexSchema.V2ReasoningSummaryPartAddedNotification; + readonly "item/reasoning/textDelta": CodexSchema.V2ReasoningTextDeltaNotification; + readonly "thread/compacted": CodexSchema.V2ContextCompactedNotification; + readonly "model/rerouted": CodexSchema.V2ModelReroutedNotification; + readonly "model/verification": CodexSchema.V2ModelVerificationNotification; + readonly warning: CodexSchema.V2WarningNotification; + readonly guardianWarning: CodexSchema.V2GuardianWarningNotification; + readonly deprecationNotice: CodexSchema.V2DeprecationNoticeNotification; + readonly configWarning: CodexSchema.V2ConfigWarningNotification; + readonly "fuzzyFileSearch/sessionUpdated": CodexSchema.FuzzyFileSearchSessionUpdatedNotification; + readonly "fuzzyFileSearch/sessionCompleted": CodexSchema.FuzzyFileSearchSessionCompletedNotification; + readonly "thread/realtime/started": CodexSchema.V2ThreadRealtimeStartedNotification; + readonly "thread/realtime/itemAdded": CodexSchema.V2ThreadRealtimeItemAddedNotification; + readonly "thread/realtime/transcript/delta": CodexSchema.V2ThreadRealtimeTranscriptDeltaNotification; + readonly "thread/realtime/transcript/done": CodexSchema.V2ThreadRealtimeTranscriptDoneNotification; + readonly "thread/realtime/outputAudio/delta": CodexSchema.V2ThreadRealtimeOutputAudioDeltaNotification; + readonly "thread/realtime/sdp": CodexSchema.V2ThreadRealtimeSdpNotification; + readonly "thread/realtime/error": CodexSchema.V2ThreadRealtimeErrorNotification; + readonly "thread/realtime/closed": CodexSchema.V2ThreadRealtimeClosedNotification; + readonly "windows/worldWritableWarning": CodexSchema.V2WindowsWorldWritableWarningNotification; + readonly "windowsSandbox/setupCompleted": CodexSchema.V2WindowsSandboxSetupCompletedNotification; + readonly "account/login/completed": CodexSchema.V2AccountLoginCompletedNotification; } export const CLIENT_REQUEST_PARAMS = { diff --git a/tsconfig.base.json b/tsconfig.base.json index e68fce2d699..a84f620ba86 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -35,6 +35,7 @@ "globalErrorInEffectFailure": "error", "unknownInEffectCatch": "error", "strictBooleanExpressions": "off", + "lazyEffect": "off", "preferSchemaOverJson": "error", "schemaSyncInEffect": "error", "cryptoRandomUUID": "error", From 52825a33a3a9dd74ea14555cb96884d28b83ce72 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 15:51:37 -0700 Subject: [PATCH 09/10] Simplify web Effect diagnostic overrides Co-authored-by: codex --- apps/web/tsconfig.json | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 98505f0d1a0..d4efb2dcff4 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -15,22 +15,7 @@ "plugins": [ { "name": "@effect/language-service", - "namespaceImportPackages": ["@effect/platform-node", "effect"], "diagnosticSeverity": { - "importFromBarrel": "error", - "anyUnknownInErrorContext": "error", - "unsafeEffectTypeAssertion": "error", - "instanceOfSchema": "error", - "deterministicKeys": "error", - "strictEffectProvide": "off", - "missingEffectServiceDependency": "error", - "leakingRequirements": "error", - "globalErrorInEffectCatch": "error", - "globalErrorInEffectFailure": "error", - "unknownInEffectCatch": "error", - "strictBooleanExpressions": "off", - "preferSchemaOverJson": "error", - "schemaSyncInEffect": "error", "globalDate": "off", "globalConsole": "off", "globalRandom": "off", From c13d21c147b617fbf52b67a460788c3dd008d918 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 28 May 2026 15:52:31 -0700 Subject: [PATCH 10/10] Document web Effect diagnostic inheritance Co-authored-by: codex --- apps/web/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index d4efb2dcff4..cea82976917 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -15,6 +15,7 @@ "plugins": [ { "name": "@effect/language-service", + // Diagnostic severities are deep-merged with tsconfig.base.json; list only web-specific overrides here. "diagnosticSeverity": { "globalDate": "off", "globalConsole": "off",