authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-05-28 15:59:42-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-05-28 15:59:42-07:00
log6b3050ee740f510ad06c12a91ecd7e338792dce0
tree41c288ff5d92c343fc0685793eaac651ea7e19fb
parent83f0cc9e31b8c38cc3ecd3c394f882ce9ee3714f
signature Signed by PGP key B5690EEEBB952194

Migrate TypeScript checks to Effect TSGo (#2851)


102 files changed, 827 insertions(+), 831 deletions(-)

apps/desktop/package.json+1-3
...@@ -10,7 +10,7 @@...@@ -10,7 +10,7 @@
10 "dev:electron": "node scripts/dev-electron.mjs",10 "dev:electron": "node scripts/dev-electron.mjs",
11 "build": "tsdown",11 "build": "tsdown",
12 "start": "node scripts/start-electron.mjs",12 "start": "node scripts/start-electron.mjs",
13 "typecheck": "tsc --noEmit",13 "typecheck": "tsgo --noEmit",
14 "test": "vitest run --passWithNoTests",14 "test": "vitest run --passWithNoTests",
15 "smoke-test": "node scripts/smoke-test.mjs"15 "smoke-test": "node scripts/smoke-test.mjs"
16 },16 },
...@@ -25,11 +25,9 @@...@@ -25,11 +25,9 @@
25 "electron-updater": "^6.6.2"25 "electron-updater": "^6.6.2"
26 },26 },
27 "devDependencies": {27 "devDependencies": {
28 "@effect/language-service": "catalog:",
29 "@effect/vitest": "catalog:",28 "@effect/vitest": "catalog:",
30 "@types/node": "catalog:",29 "@types/node": "catalog:",
31 "tsdown": "catalog:",30 "tsdown": "catalog:",
32 "typescript": "catalog:",
33 "vitest": "catalog:"31 "vitest": "catalog:"
34 },32 },
35 "productName": "T3 Code (Alpha)"33 "productName": "T3 Code (Alpha)"
apps/desktop/src/app/DesktopAppIdentity.ts+1-1
...@@ -26,7 +26,7 @@ export interface DesktopAppIdentityShape {...@@ -26,7 +26,7 @@ export interface DesktopAppIdentityShape {
26export class DesktopAppIdentity extends Context.Service<26export class DesktopAppIdentity extends Context.Service<
27 DesktopAppIdentity,27 DesktopAppIdentity,
28 DesktopAppIdentityShape28 DesktopAppIdentityShape
29>()("t3/desktop/AppIdentity") {}29>()("@t3tools/desktop/app/DesktopAppIdentity") {}
3030
31const normalizeCommitHash = (value: string): Option.Option<string> => {31const normalizeCommitHash = (value: string): Option.Option<string> => {
32 const trimmed = value.trim();32 const trimmed = value.trim();
apps/desktop/src/app/DesktopAssets.ts+1-1
...@@ -18,7 +18,7 @@ export interface DesktopAssetsShape {...@@ -18,7 +18,7 @@ export interface DesktopAssetsShape {
18}18}
1919
20export class DesktopAssets extends Context.Service<DesktopAssets, DesktopAssetsShape>()(20export class DesktopAssets extends Context.Service<DesktopAssets, DesktopAssetsShape>()(
21 "t3/desktop/Assets",21 "@t3tools/desktop/app/DesktopAssets",
22) {}22) {}
2323
24const resolveResourcePath = Effect.fn("desktop.assets.resolveResourcePath")(function* (24const resolveResourcePath = Effect.fn("desktop.assets.resolveResourcePath")(function* (
apps/desktop/src/app/DesktopEnvironment.test.ts+1-3
...@@ -32,9 +32,7 @@ const makeEnvironment = (...@@ -32,9 +32,7 @@ const makeEnvironment = (
32 overrides: Partial<DesktopEnvironment.MakeDesktopEnvironmentInput> = {},32 overrides: Partial<DesktopEnvironment.MakeDesktopEnvironmentInput> = {},
33 env: Record<string, string | undefined> = {},33 env: Record<string, string | undefined> = {},
34) =>34) =>
35 Effect.gen(function* () {35 DesktopEnvironment.DesktopEnvironment.pipe(Effect.provide(makeEnvironmentLayer(overrides, env)));
36 return yield* DesktopEnvironment.DesktopEnvironment;
37 }).pipe(Effect.provide(makeEnvironmentLayer(overrides, env)));
3836
39describe("DesktopEnvironment", () => {37describe("DesktopEnvironment", () => {
40 it.effect("derives state paths and development identity inside Effect", () =>38 it.effect("derives state paths and development identity inside Effect", () =>
apps/desktop/src/app/DesktopEnvironment.ts+1-1
...@@ -78,7 +78,7 @@ export interface DesktopEnvironmentShape {...@@ -78,7 +78,7 @@ export interface DesktopEnvironmentShape {
78export class DesktopEnvironment extends Context.Service<78export class DesktopEnvironment extends Context.Service<
79 DesktopEnvironment,79 DesktopEnvironment,
80 DesktopEnvironmentShape80 DesktopEnvironmentShape
81>()("t3/desktop/Environment") {}81>()("@t3tools/desktop/app/DesktopEnvironment") {}
8282
83const APP_BASE_NAME = "T3 Code";83const APP_BASE_NAME = "T3 Code";
8484
apps/desktop/src/app/DesktopLifecycle.ts+5-2
...@@ -24,7 +24,7 @@ export interface DesktopShutdownShape {...@@ -24,7 +24,7 @@ export interface DesktopShutdownShape {
24}24}
2525
26export class DesktopShutdown extends Context.Service<DesktopShutdown, DesktopShutdownShape>()(26export class DesktopShutdown extends Context.Service<DesktopShutdown, DesktopShutdownShape>()(
27 "t3/desktop/Shutdown",27 "@t3tools/desktop/app/DesktopLifecycle/DesktopShutdown",
28) {}28) {}
2929
30const makeShutdown = Effect.gen(function* () {30const makeShutdown = Effect.gen(function* () {
...@@ -61,8 +61,11 @@ export interface DesktopLifecycleShape {...@@ -61,8 +61,11 @@ export interface DesktopLifecycleShape {
61 readonly register: Effect.Effect<void, never, Scope.Scope | DesktopLifecycleRuntimeServices>;61 readonly register: Effect.Effect<void, never, Scope.Scope | DesktopLifecycleRuntimeServices>;
62}62}
6363
64/**
65 * @effect-expect-leaking DesktopEnvironment | DesktopShutdown | DesktopState | DesktopWindow | ElectronApp | ElectronTheme
66 */
64export class DesktopLifecycle extends Context.Service<DesktopLifecycle, DesktopLifecycleShape>()(67export class DesktopLifecycle extends Context.Service<DesktopLifecycle, DesktopLifecycleShape>()(
65 "t3/desktop/Lifecycle",68 "@t3tools/desktop/app/DesktopLifecycle",
66) {}69) {}
6770
68const { logInfo: logLifecycleInfo, logError: logLifecycleError } =71const { logInfo: logLifecycleInfo, logError: logLifecycleError } =
apps/desktop/src/app/DesktopObservability.ts+1-1
...@@ -43,7 +43,7 @@ export interface DesktopBackendOutputLogShape {...@@ -43,7 +43,7 @@ export interface DesktopBackendOutputLogShape {
43export class DesktopBackendOutputLog extends Context.Service<43export class DesktopBackendOutputLog extends Context.Service<
44 DesktopBackendOutputLog,44 DesktopBackendOutputLog,
45 DesktopBackendOutputLogShape45 DesktopBackendOutputLogShape
46>()("t3/desktop/BackendOutputLog") {}46>()("@t3tools/desktop/app/DesktopObservability/DesktopBackendOutputLog") {}
4747
48const textEncoder = new TextEncoder();48const textEncoder = new TextEncoder();
49const textDecoder = new TextDecoder();49const textDecoder = new TextDecoder();
apps/desktop/src/app/DesktopState.ts+1-1
...@@ -9,7 +9,7 @@ export interface DesktopStateShape {...@@ -9,7 +9,7 @@ export interface DesktopStateShape {
9}9}
1010
11export class DesktopState extends Context.Service<DesktopState, DesktopStateShape>()(11export class DesktopState extends Context.Service<DesktopState, DesktopStateShape>()(
12 "t3/desktop/State",12 "@t3tools/desktop/app/DesktopState",
13) {}13) {}
1414
15export const layer = Layer.effect(15export const layer = Layer.effect(
apps/desktop/src/backend/DesktopBackendConfiguration.ts+1-1
...@@ -24,7 +24,7 @@ export interface DesktopBackendConfigurationShape {...@@ -24,7 +24,7 @@ export interface DesktopBackendConfigurationShape {
24export class DesktopBackendConfiguration extends Context.Service<24export class DesktopBackendConfiguration extends Context.Service<
25 DesktopBackendConfiguration,25 DesktopBackendConfiguration,
26 DesktopBackendConfigurationShape26 DesktopBackendConfigurationShape
27>()("t3/desktop/BackendConfiguration") {}27>()("@t3tools/desktop/backend/DesktopBackendConfiguration") {}
2828
29interface BackendObservabilitySettings {29interface BackendObservabilitySettings {
30 readonly otlpTracesUrl: Option.Option<string>;30 readonly otlpTracesUrl: Option.Option<string>;
apps/desktop/src/backend/DesktopBackendManager.ts+1-1
...@@ -116,7 +116,7 @@ export interface DesktopBackendManagerShape {...@@ -116,7 +116,7 @@ export interface DesktopBackendManagerShape {
116export class DesktopBackendManager extends Context.Service<116export class DesktopBackendManager extends Context.Service<
117 DesktopBackendManager,117 DesktopBackendManager,
118 DesktopBackendManagerShape118 DesktopBackendManagerShape
119>()("t3/desktop/BackendManager") {}119>()("@t3tools/desktop/backend/DesktopBackendManager") {}
120120
121const { logWarning: logBackendManagerWarning, logError: logBackendManagerError } =121const { logWarning: logBackendManagerWarning, logError: logBackendManagerError } =
122 DesktopObservability.makeComponentLogger("desktop-backend-manager");122 DesktopObservability.makeComponentLogger("desktop-backend-manager");
apps/desktop/src/backend/DesktopServerExposure.ts+2-2
...@@ -275,7 +275,7 @@ export interface DesktopServerExposureShape {...@@ -275,7 +275,7 @@ export interface DesktopServerExposureShape {
275export class DesktopServerExposure extends Context.Service<275export class DesktopServerExposure extends Context.Service<
276 DesktopServerExposure,276 DesktopServerExposure,
277 DesktopServerExposureShape277 DesktopServerExposureShape
278>()("t3/desktop/ServerExposure") {}278>()("@t3tools/desktop/backend/DesktopServerExposure") {}
279279
280export interface DesktopNetworkInterfacesServiceShape {280export interface DesktopNetworkInterfacesServiceShape {
281 readonly read: Effect.Effect<DesktopNetworkInterfaces>;281 readonly read: Effect.Effect<DesktopNetworkInterfaces>;
...@@ -284,7 +284,7 @@ export interface DesktopNetworkInterfacesServiceShape {...@@ -284,7 +284,7 @@ export interface DesktopNetworkInterfacesServiceShape {
284export class DesktopNetworkInterfacesService extends Context.Service<284export class DesktopNetworkInterfacesService extends Context.Service<
285 DesktopNetworkInterfacesService,285 DesktopNetworkInterfacesService,
286 DesktopNetworkInterfacesServiceShape286 DesktopNetworkInterfacesServiceShape
287>()("t3/desktop/ServerExposure/NetworkInterfaces") {}287>()("@t3tools/desktop/backend/DesktopServerExposure/DesktopNetworkInterfacesService") {}
288288
289interface RuntimeState {289interface RuntimeState {
290 readonly requestedMode: DesktopServerExposureMode;290 readonly requestedMode: DesktopServerExposureMode;
apps/desktop/src/electron/ElectronApp.ts+1-1
...@@ -39,7 +39,7 @@ export interface ElectronAppShape {...@@ -39,7 +39,7 @@ export interface ElectronAppShape {
39}39}
4040
41export class ElectronApp extends Context.Service<ElectronApp, ElectronAppShape>()(41export class ElectronApp extends Context.Service<ElectronApp, ElectronAppShape>()(
42 "t3/desktop/electron/App",42 "@t3tools/desktop/electron/ElectronApp",
43) {}43) {}
4444
45const addScopedAppListener = <Args extends ReadonlyArray<unknown>>(45const addScopedAppListener = <Args extends ReadonlyArray<unknown>>(
apps/desktop/src/electron/ElectronDialog.ts+1-1
...@@ -29,7 +29,7 @@ export interface ElectronDialogShape {...@@ -29,7 +29,7 @@ export interface ElectronDialogShape {
29}29}
3030
31export class ElectronDialog extends Context.Service<ElectronDialog, ElectronDialogShape>()(31export class ElectronDialog extends Context.Service<ElectronDialog, ElectronDialogShape>()(
32 "t3/desktop/electron/Dialog",32 "@t3tools/desktop/electron/ElectronDialog",
33) {}33) {}
3434
35const make = ElectronDialog.of({35const make = ElectronDialog.of({
apps/desktop/src/electron/ElectronMenu.ts+1-1
...@@ -33,7 +33,7 @@ export interface ElectronMenuShape {...@@ -33,7 +33,7 @@ export interface ElectronMenuShape {
33}33}
3434
35export class ElectronMenu extends Context.Service<ElectronMenu, ElectronMenuShape>()(35export class ElectronMenu extends Context.Service<ElectronMenu, ElectronMenuShape>()(
36 "t3/desktop/electron/Menu",36 "@t3tools/desktop/electron/ElectronMenu",
37) {}37) {}
3838
39function normalizeContextMenuItems(source: readonly ContextMenuItem[]): ContextMenuItem[] {39function normalizeContextMenuItems(source: readonly ContextMenuItem[]): ContextMenuItem[] {
apps/desktop/src/electron/ElectronProtocol.ts+1-1
...@@ -52,7 +52,7 @@ export interface ElectronProtocolShape {...@@ -52,7 +52,7 @@ export interface ElectronProtocolShape {
52}52}
5353
54export class ElectronProtocol extends Context.Service<ElectronProtocol, ElectronProtocolShape>()(54export class ElectronProtocol extends Context.Service<ElectronProtocol, ElectronProtocolShape>()(
55 "t3/desktop/electron/Protocol",55 "@t3tools/desktop/electron/ElectronProtocol",
56) {}56) {}
5757
58export function normalizeDesktopProtocolPathname(rawPath: string): Option.Option<string> {58export function normalizeDesktopProtocolPathname(rawPath: string): Option.Option<string> {
apps/desktop/src/electron/ElectronSafeStorage.ts+1-1
...@@ -48,7 +48,7 @@ export interface ElectronSafeStorageShape {...@@ -48,7 +48,7 @@ export interface ElectronSafeStorageShape {
48export class ElectronSafeStorage extends Context.Service<48export class ElectronSafeStorage extends Context.Service<
49 ElectronSafeStorage,49 ElectronSafeStorage,
50 ElectronSafeStorageShape50 ElectronSafeStorageShape
51>()("@t3tools/desktop/ElectronSafeStorage") {}51>()("@t3tools/desktop/electron/ElectronSafeStorage") {}
5252
53const make = ElectronSafeStorage.of({53const make = ElectronSafeStorage.of({
54 isEncryptionAvailable: Effect.try({54 isEncryptionAvailable: Effect.try({
apps/desktop/src/electron/ElectronShell.ts+1-1
...@@ -26,7 +26,7 @@ export interface ElectronShellShape {...@@ -26,7 +26,7 @@ export interface ElectronShellShape {
26}26}
2727
28export class ElectronShell extends Context.Service<ElectronShell, ElectronShellShape>()(28export class ElectronShell extends Context.Service<ElectronShell, ElectronShellShape>()(
29 "t3/desktop/electron/Shell",29 "@t3tools/desktop/electron/ElectronShell",
30) {}30) {}
3131
32const make = ElectronShell.of({32const make = ElectronShell.of({
apps/desktop/src/electron/ElectronTheme.ts+1-1
...@@ -13,7 +13,7 @@ export interface ElectronThemeShape {...@@ -13,7 +13,7 @@ export interface ElectronThemeShape {
13}13}
1414
15export class ElectronTheme extends Context.Service<ElectronTheme, ElectronThemeShape>()(15export class ElectronTheme extends Context.Service<ElectronTheme, ElectronThemeShape>()(
16 "t3/desktop/electron/Theme",16 "@t3tools/desktop/electron/ElectronTheme",
17) {}17) {}
1818
19const make = ElectronTheme.of({19const make = ElectronTheme.of({
apps/desktop/src/electron/ElectronUpdater.ts+1-1
...@@ -67,7 +67,7 @@ export interface ElectronUpdaterShape {...@@ -67,7 +67,7 @@ export interface ElectronUpdaterShape {
67}67}
6868
69export class ElectronUpdater extends Context.Service<ElectronUpdater, ElectronUpdaterShape>()(69export class ElectronUpdater extends Context.Service<ElectronUpdater, ElectronUpdaterShape>()(
70 "t3/desktop/electron/Updater",70 "@t3tools/desktop/electron/ElectronUpdater",
71) {}71) {}
7272
73export const layer = Layer.succeed(ElectronUpdater, {73export const layer = Layer.succeed(ElectronUpdater, {
apps/desktop/src/electron/ElectronWindow.ts+1-1
...@@ -33,7 +33,7 @@ export interface ElectronWindowShape {...@@ -33,7 +33,7 @@ export interface ElectronWindowShape {
33}33}
3434
35export class ElectronWindow extends Context.Service<ElectronWindow, ElectronWindowShape>()(35export class ElectronWindow extends Context.Service<ElectronWindow, ElectronWindowShape>()(
36 "t3/desktop/electron/Window",36 "@t3tools/desktop/electron/ElectronWindow",
37) {}37) {}
3838
39const make = Effect.gen(function* () {39const make = Effect.gen(function* () {
apps/desktop/src/ipc/DesktopIpc.ts+3-1
...@@ -42,7 +42,9 @@ export interface DesktopIpcShape {...@@ -42,7 +42,9 @@ export interface DesktopIpcShape {
42 ) => Effect.Effect<void, never, R | Scope.Scope>;42 ) => Effect.Effect<void, never, R | Scope.Scope>;
43}43}
4444
45export class DesktopIpc extends Context.Service<DesktopIpc, DesktopIpcShape>()("t3/desktop/Ipc") {}45export class DesktopIpc extends Context.Service<DesktopIpc, DesktopIpcShape>()(
46 "@t3tools/desktop/ipc/DesktopIpc",
47) {}
4648
47export const make = (ipcMain: DesktopIpcMain): DesktopIpcShape =>49export const make = (ipcMain: DesktopIpcMain): DesktopIpcShape =>
48 DesktopIpc.of({50 DesktopIpc.of({
apps/desktop/src/settings/DesktopAppSettings.ts+1-1
...@@ -89,7 +89,7 @@ export interface DesktopAppSettingsShape {...@@ -89,7 +89,7 @@ export interface DesktopAppSettingsShape {
89export class DesktopAppSettings extends Context.Service<89export class DesktopAppSettings extends Context.Service<
90 DesktopAppSettings,90 DesktopAppSettings,
91 DesktopAppSettingsShape91 DesktopAppSettingsShape
92>()("t3/desktop/AppSettings") {}92>()("@t3tools/desktop/settings/DesktopAppSettings") {}
9393
94export function resolveDefaultDesktopSettings(appVersion: string): DesktopSettings {94export function resolveDefaultDesktopSettings(appVersion: string): DesktopSettings {
95 return {95 return {
apps/desktop/src/settings/DesktopClientSettings.ts+1-1
...@@ -49,7 +49,7 @@ export interface DesktopClientSettingsShape {...@@ -49,7 +49,7 @@ export interface DesktopClientSettingsShape {
49export class DesktopClientSettings extends Context.Service<49export class DesktopClientSettings extends Context.Service<
50 DesktopClientSettings,50 DesktopClientSettings,
51 DesktopClientSettingsShape51 DesktopClientSettingsShape
52>()("t3/desktop/ClientSettings") {}52>()("@t3tools/desktop/settings/DesktopClientSettings") {}
5353
54const readClientSettings = (54const readClientSettings = (
55 fileSystem: FileSystem.FileSystem,55 fileSystem: FileSystem.FileSystem,
apps/desktop/src/settings/DesktopSavedEnvironments.ts+1-1
...@@ -121,7 +121,7 @@ export interface DesktopSavedEnvironmentsShape {...@@ -121,7 +121,7 @@ export interface DesktopSavedEnvironmentsShape {
121export class DesktopSavedEnvironments extends Context.Service<121export class DesktopSavedEnvironments extends Context.Service<
122 DesktopSavedEnvironments,122 DesktopSavedEnvironments,
123 DesktopSavedEnvironmentsShape123 DesktopSavedEnvironmentsShape
124>()("t3/desktop/SavedEnvironments") {}124>()("@t3tools/desktop/settings/DesktopSavedEnvironments") {}
125125
126function toPersistedSavedEnvironmentRecord(126function toPersistedSavedEnvironmentRecord(
127 record: PersistedSavedEnvironmentStorageRecord,127 record: PersistedSavedEnvironmentStorageRecord,
apps/desktop/src/shell/DesktopShellEnvironment.ts+1-1
...@@ -26,7 +26,7 @@ export interface DesktopShellEnvironmentShape {...@@ -26,7 +26,7 @@ export interface DesktopShellEnvironmentShape {
26export class DesktopShellEnvironment extends Context.Service<26export class DesktopShellEnvironment extends Context.Service<
27 DesktopShellEnvironment,27 DesktopShellEnvironment,
28 DesktopShellEnvironmentShape28 DesktopShellEnvironmentShape
29>()("t3/desktop/ShellEnvironment") {}29>()("@t3tools/desktop/shell/DesktopShellEnvironment") {}
3030
31const LOGIN_SHELL_ENV_NAMES = [31const LOGIN_SHELL_ENV_NAMES = [
32 "PATH",32 "PATH",
apps/desktop/src/ssh/DesktopSshEnvironment.ts+1-1
...@@ -68,7 +68,7 @@ export interface DesktopSshEnvironmentShape {...@@ -68,7 +68,7 @@ export interface DesktopSshEnvironmentShape {
68export class DesktopSshEnvironment extends Context.Service<68export class DesktopSshEnvironment extends Context.Service<
69 DesktopSshEnvironment,69 DesktopSshEnvironment,
70 DesktopSshEnvironmentShape70 DesktopSshEnvironmentShape
71>()("t3/desktop/SshEnvironment") {}71>()("@t3tools/desktop/ssh/DesktopSshEnvironment") {}
7272
73export interface DesktopSshEnvironmentLayerOptions {73export interface DesktopSshEnvironmentLayerOptions {
74 readonly resolveCliPackageSpec?: () => string;74 readonly resolveCliPackageSpec?: () => string;
apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts+1-1
...@@ -129,7 +129,7 @@ export interface DesktopSshPasswordPromptsShape {...@@ -129,7 +129,7 @@ export interface DesktopSshPasswordPromptsShape {
129export class DesktopSshPasswordPrompts extends Context.Service<129export class DesktopSshPasswordPrompts extends Context.Service<
130 DesktopSshPasswordPrompts,130 DesktopSshPasswordPrompts,
131 DesktopSshPasswordPromptsShape131 DesktopSshPasswordPromptsShape
132>()("t3/desktop/SshPasswordPrompts") {}132>()("@t3tools/desktop/ssh/DesktopSshPasswordPrompts") {}
133133
134interface PendingSshPasswordPrompt {134interface PendingSshPasswordPrompt {
135 readonly requestId: string;135 readonly requestId: string;
apps/desktop/src/ssh/DesktopSshRemoteApi.ts+1-1
...@@ -53,7 +53,7 @@ export interface DesktopSshRemoteApiShape {...@@ -53,7 +53,7 @@ export interface DesktopSshRemoteApiShape {
53export class DesktopSshRemoteApi extends Context.Service<53export class DesktopSshRemoteApi extends Context.Service<
54 DesktopSshRemoteApi,54 DesktopSshRemoteApi,
55 DesktopSshRemoteApiShape55 DesktopSshRemoteApiShape
56>()("t3/desktop/SshRemoteApi") {}56>()("@t3tools/desktop/ssh/DesktopSshRemoteApi") {}
5757
58const decodeExecutionEnvironmentDescriptor = Schema.decodeUnknownEffect(58const decodeExecutionEnvironmentDescriptor = Schema.decodeUnknownEffect(
59 ExecutionEnvironmentDescriptor,59 ExecutionEnvironmentDescriptor,
apps/desktop/src/updates/DesktopUpdates.ts+1-1
...@@ -100,7 +100,7 @@ export interface DesktopUpdatesShape {...@@ -100,7 +100,7 @@ export interface DesktopUpdatesShape {
100}100}
101101
102export class DesktopUpdates extends Context.Service<DesktopUpdates, DesktopUpdatesShape>()(102export class DesktopUpdates extends Context.Service<DesktopUpdates, DesktopUpdatesShape>()(
103 "t3/desktop/Updates",103 "@t3tools/desktop/updates/DesktopUpdates",
104) {}104) {}
105105
106const {106const {
apps/desktop/src/window/DesktopApplicationMenu.ts+1-1
...@@ -21,7 +21,7 @@ export interface DesktopApplicationMenuShape {...@@ -21,7 +21,7 @@ export interface DesktopApplicationMenuShape {
21export class DesktopApplicationMenu extends Context.Service<21export class DesktopApplicationMenu extends Context.Service<
22 DesktopApplicationMenu,22 DesktopApplicationMenu,
23 DesktopApplicationMenuShape23 DesktopApplicationMenuShape
24>()("t3/desktop/ApplicationMenu") {}24>()("@t3tools/desktop/window/DesktopApplicationMenu") {}
2525
26type DesktopApplicationMenuRuntimeServices =26type DesktopApplicationMenuRuntimeServices =
27 | DesktopUpdates.DesktopUpdates27 | DesktopUpdates.DesktopUpdates
apps/desktop/src/window/DesktopWindow.ts+1-1
...@@ -62,7 +62,7 @@ export interface DesktopWindowShape {...@@ -62,7 +62,7 @@ export interface DesktopWindowShape {
62}62}
6363
64export class DesktopWindow extends Context.Service<DesktopWindow, DesktopWindowShape>()(64export class DesktopWindow extends Context.Service<DesktopWindow, DesktopWindowShape>()(
65 "t3/desktop/Window",65 "@t3tools/desktop/window/DesktopWindow",
66) {}66) {}
6767
68const { logInfo: logWindowInfo, logWarning: logWindowWarning } =68const { logInfo: logWindowInfo, logWarning: logWindowWarning } =
apps/server/package.json+1-3
...@@ -19,7 +19,7 @@...@@ -19,7 +19,7 @@
19 "build": "node scripts/cli.ts build",19 "build": "node scripts/cli.ts build",
20 "build:bundle": "tsdown",20 "build:bundle": "tsdown",
21 "start": "node dist/bin.mjs",21 "start": "node dist/bin.mjs",
22 "typecheck": "tsc --noEmit",22 "typecheck": "tsgo --noEmit",
23 "test": "vitest run"23 "test": "vitest run"
24 },24 },
25 "dependencies": {25 "dependencies": {
...@@ -34,7 +34,6 @@...@@ -34,7 +34,6 @@
34 "node-pty": "^1.1.0"34 "node-pty": "^1.1.0"
35 },35 },
36 "devDependencies": {36 "devDependencies": {
37 "@effect/language-service": "catalog:",
38 "@effect/vitest": "catalog:",37 "@effect/vitest": "catalog:",
39 "@t3tools/contracts": "workspace:*",38 "@t3tools/contracts": "workspace:*",
40 "@t3tools/shared": "workspace:*",39 "@t3tools/shared": "workspace:*",
...@@ -45,7 +44,6 @@...@@ -45,7 +44,6 @@
45 "effect-acp": "workspace:*",44 "effect-acp": "workspace:*",
46 "effect-codex-app-server": "workspace:*",45 "effect-codex-app-server": "workspace:*",
47 "tsdown": "catalog:",46 "tsdown": "catalog:",
48 "typescript": "catalog:",
49 "vitest": "catalog:"47 "vitest": "catalog:"
50 },48 },
51 "engines": {49 "engines": {
apps/server/src/auth/Layers/BootstrapCredentialService.ts+3-1
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1import type { AuthPairingLink } from "@t3tools/contracts";1import type { AuthPairingLink } from "@t3tools/contracts";
2import * as Crypto from "effect/Crypto";
2import * as DateTime from "effect/DateTime";3import * as DateTime from "effect/DateTime";
3import * as Duration from "effect/Duration";4import * as Duration from "effect/Duration";
4import * as Effect from "effect/Effect";5import * as Effect from "effect/Effect";
...@@ -46,6 +47,7 @@ const generatePairingToken = (): string => {...@@ -46,6 +47,7 @@ const generatePairingToken = (): string => {
46};47};
4748
48export const makeBootstrapCredentialService = Effect.gen(function* () {49export const makeBootstrapCredentialService = Effect.gen(function* () {
50 const crypto = yield* Crypto.Crypto;
49 const config = yield* ServerConfig;51 const config = yield* ServerConfig;
50 const pairingLinks = yield* AuthPairingLinkRepository;52 const pairingLinks = yield* AuthPairingLinkRepository;
51 const seededGrantsRef = yield* Ref.make(new Map<string, StoredBootstrapGrant>());53 const seededGrantsRef = yield* Ref.make(new Map<string, StoredBootstrapGrant>());
...@@ -141,7 +143,7 @@ export const makeBootstrapCredentialService = Effect.gen(function* () {...@@ -141,7 +143,7 @@ export const makeBootstrapCredentialService = Effect.gen(function* () {
141143
142 const issueOneTimeToken: BootstrapCredentialServiceShape["issueOneTimeToken"] = (input) =>144 const issueOneTimeToken: BootstrapCredentialServiceShape["issueOneTimeToken"] = (input) =>
143 Effect.gen(function* () {145 Effect.gen(function* () {
144 const id = crypto.randomUUID();146 const id = yield* crypto.randomUUIDv4;
145 const credential = generatePairingToken();147 const credential = generatePairingToken();
146 const ttl = input?.ttl ?? DEFAULT_ONE_TIME_TOKEN_TTL_MINUTES;148 const ttl = input?.ttl ?? DEFAULT_ONE_TIME_TOKEN_TTL_MINUTES;
147 const now = yield* DateTime.now;149 const now = yield* DateTime.now;
apps/server/src/auth/Layers/SessionCredentialService.ts+3-1
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1import { AuthSessionId, type AuthClientMetadata, type AuthClientSession } from "@t3tools/contracts";1import { AuthSessionId, type AuthClientMetadata, type AuthClientSession } from "@t3tools/contracts";
2import * as Clock from "effect/Clock";2import * as Clock from "effect/Clock";
3import * as Crypto from "effect/Crypto";
3import * as DateTime from "effect/DateTime";4import * as DateTime from "effect/DateTime";
4import * as Duration from "effect/Duration";5import * as Duration from "effect/Duration";
5import * as Effect from "effect/Effect";6import * as Effect from "effect/Effect";
...@@ -90,6 +91,7 @@ function toAuthClientSession(input: Omit<AuthClientSession, "current">): AuthCli...@@ -90,6 +91,7 @@ function toAuthClientSession(input: Omit<AuthClientSession, "current">): AuthCli
90}91}
9192
92export const makeSessionCredentialService = Effect.gen(function* () {93export const makeSessionCredentialService = Effect.gen(function* () {
94 const crypto = yield* Crypto.Crypto;
93 const serverConfig = yield* ServerConfig;95 const serverConfig = yield* ServerConfig;
94 const secretStore = yield* ServerSecretStore;96 const secretStore = yield* ServerSecretStore;
95 const authSessions = yield* AuthSessionRepository;97 const authSessions = yield* AuthSessionRepository;
...@@ -203,7 +205,7 @@ export const makeSessionCredentialService = Effect.gen(function* () {...@@ -203,7 +205,7 @@ export const makeSessionCredentialService = Effect.gen(function* () {
203 const encodeClaims = Schema.encodeEffect(Schema.fromJsonString(SessionClaims));205 const encodeClaims = Schema.encodeEffect(Schema.fromJsonString(SessionClaims));
204 const issue: SessionCredentialServiceShape["issue"] = (input) =>206 const issue: SessionCredentialServiceShape["issue"] = (input) =>
205 Effect.gen(function* () {207 Effect.gen(function* () {
206 const sessionId = AuthSessionId.make(crypto.randomUUID());208 const sessionId = AuthSessionId.make(yield* crypto.randomUUIDv4);
207 const issuedAt = yield* DateTime.now;209 const issuedAt = yield* DateTime.now;
208 const expiresAt = DateTime.add(issuedAt, {210 const expiresAt = DateTime.add(issuedAt, {
209 milliseconds: Duration.toMillis(input?.ttl ?? DEFAULT_SESSION_TTL),211 milliseconds: Duration.toMillis(input?.ttl ?? DEFAULT_SESSION_TTL),
apps/server/src/auth/Services/AuthControlPlane.ts+1-1
...@@ -69,5 +69,5 @@ export interface AuthControlPlaneShape {...@@ -69,5 +69,5 @@ export interface AuthControlPlaneShape {
69}69}
7070
71export class AuthControlPlane extends Context.Service<AuthControlPlane, AuthControlPlaneShape>()(71export class AuthControlPlane extends Context.Service<AuthControlPlane, AuthControlPlaneShape>()(
72 "t3/AuthControlPlane",72 "t3/auth/Services/AuthControlPlane",
73) {}73) {}
apps/server/src/bin.test.ts+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1// @effect-diagnostics-next-line nodeBuiltinImport:off - NodeHttpServer.layer takes `NodeHttp.createServer` as arg1// @effect-diagnostics nodeBuiltinImport:off - CLI integration exercises Node HTTP and filesystem boundaries.
2import * as NodeHttp from "node:http";2import * as NodeHttp from "node:http";
3import { mkdtempSync } from "node:fs";3import { mkdtempSync } from "node:fs";
4import { tmpdir } from "node:os";4import { tmpdir } from "node:os";
apps/server/src/orchestration/Layers/CheckpointReactor.ts+63-41
...@@ -9,10 +9,12 @@ import {...@@ -9,10 +9,12 @@ import {
9 type ProviderRuntimeEvent,9 type ProviderRuntimeEvent,
10} from "@t3tools/contracts";10} from "@t3tools/contracts";
11import * as Cause from "effect/Cause";11import * as Cause from "effect/Cause";
12import * as Crypto from "effect/Crypto";
12import * as DateTime from "effect/DateTime";13import * as DateTime from "effect/DateTime";
13import * as Effect from "effect/Effect";14import * as Effect from "effect/Effect";
14import * as Layer from "effect/Layer";15import * as Layer from "effect/Layer";
15import * as Option from "effect/Option";16import * as Option from "effect/Option";
17import type * as PlatformError from "effect/PlatformError";
16import * as Stream from "effect/Stream";18import * as Stream from "effect/Stream";
17import { makeDrainableWorker } from "@t3tools/shared/DrainableWorker";19import { makeDrainableWorker } from "@t3tools/shared/DrainableWorker";
1820
...@@ -69,10 +71,12 @@ function checkpointStatusFromRuntime(status: string | undefined): "ready" | "mis...@@ -69,10 +71,12 @@ function checkpointStatusFromRuntime(status: string | undefined): "ready" | "mis
69 }71 }
70}72}
7173
72const serverCommandId = (tag: string): CommandId =>
73 CommandId.make(`server:${tag}:${crypto.randomUUID()}`);
74
75const make = Effect.gen(function* () {74const make = Effect.gen(function* () {
75 const crypto = yield* Crypto.Crypto;
76 const randomUUID = crypto.randomUUIDv4;
77 const serverEventId = randomUUID.pipe(Effect.map(EventId.make));
78 const serverCommandId = (tag: string) =>
79 randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`)));
76 const orchestrationEngine = yield* OrchestrationEngineService;80 const orchestrationEngine = yield* OrchestrationEngineService;
77 const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;81 const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
78 const providerService = yield* ProviderService;82 const providerService = yield* ProviderService;
...@@ -87,24 +91,31 @@ const make = Effect.gen(function* () {...@@ -87,24 +91,31 @@ const make = Effect.gen(function* () {
87 readonly detail: string;91 readonly detail: string;
88 readonly createdAt: string;92 readonly createdAt: string;
89 }) =>93 }) =>
90 orchestrationEngine.dispatch({94 Effect.all({
91 type: "thread.activity.append",
92 commandId: serverCommandId("checkpoint-revert-failure"),95 commandId: serverCommandId("checkpoint-revert-failure"),
93 threadId: input.threadId,96 activityId: serverEventId,
94 activity: {97 }).pipe(
95 id: EventId.make(crypto.randomUUID()),98 Effect.flatMap(({ commandId, activityId }) =>
96 tone: "error",99 orchestrationEngine.dispatch({
97 kind: "checkpoint.revert.failed",100 type: "thread.activity.append",
98 summary: "Checkpoint revert failed",101 commandId,
99 payload: {102 threadId: input.threadId,
100 turnCount: input.turnCount,103 activity: {
101 detail: input.detail,104 id: activityId,
102 },105 tone: "error",
103 turnId: null,106 kind: "checkpoint.revert.failed",
104 createdAt: input.createdAt,107 summary: "Checkpoint revert failed",
105 },108 payload: {
106 createdAt: input.createdAt,109 turnCount: input.turnCount,
107 });110 detail: input.detail,
111 },
112 turnId: null,
113 createdAt: input.createdAt,
114 },
115 createdAt: input.createdAt,
116 }),
117 ),
118 );
108119
109 const appendCaptureFailureActivity = (input: {120 const appendCaptureFailureActivity = (input: {
110 readonly threadId: ThreadId;121 readonly threadId: ThreadId;
...@@ -112,23 +123,30 @@ const make = Effect.gen(function* () {...@@ -112,23 +123,30 @@ const make = Effect.gen(function* () {
112 readonly detail: string;123 readonly detail: string;
113 readonly createdAt: string;124 readonly createdAt: string;
114 }) =>125 }) =>
115 orchestrationEngine.dispatch({126 Effect.all({
116 type: "thread.activity.append",
117 commandId: serverCommandId("checkpoint-capture-failure"),127 commandId: serverCommandId("checkpoint-capture-failure"),
118 threadId: input.threadId,128 activityId: serverEventId,
119 activity: {129 }).pipe(
120 id: EventId.make(crypto.randomUUID()),130 Effect.flatMap(({ commandId, activityId }) =>
121 tone: "error",131 orchestrationEngine.dispatch({
122 kind: "checkpoint.capture.failed",132 type: "thread.activity.append",
123 summary: "Checkpoint capture failed",133 commandId,
124 payload: {134 threadId: input.threadId,
125 detail: input.detail,135 activity: {
126 },136 id: activityId,
127 turnId: input.turnId,137 tone: "error",
128 createdAt: input.createdAt,138 kind: "checkpoint.capture.failed",
129 },139 summary: "Checkpoint capture failed",
130 createdAt: input.createdAt,140 payload: {
131 });141 detail: input.detail,
142 },
143 turnId: input.turnId,
144 createdAt: input.createdAt,
145 },
146 createdAt: input.createdAt,
147 }),
148 ),
149 );
132150
133 const resolveSessionRuntimeForThread = Effect.fn("resolveSessionRuntimeForThread")(function* (151 const resolveSessionRuntimeForThread = Effect.fn("resolveSessionRuntimeForThread")(function* (
134 threadId: ThreadId,152 threadId: ThreadId,
...@@ -281,7 +299,7 @@ const make = Effect.gen(function* () {...@@ -281,7 +299,7 @@ const make = Effect.gen(function* () {
281299
282 yield* orchestrationEngine.dispatch({300 yield* orchestrationEngine.dispatch({
283 type: "thread.turn.diff.complete",301 type: "thread.turn.diff.complete",
284 commandId: serverCommandId("checkpoint-turn-diff-complete"),302 commandId: yield* serverCommandId("checkpoint-turn-diff-complete"),
285 threadId: input.threadId,303 threadId: input.threadId,
286 turnId: input.turnId,304 turnId: input.turnId,
287 completedAt: input.createdAt,305 completedAt: input.createdAt,
...@@ -311,10 +329,10 @@ const make = Effect.gen(function* () {...@@ -311,10 +329,10 @@ const make = Effect.gen(function* () {
311329
312 yield* orchestrationEngine.dispatch({330 yield* orchestrationEngine.dispatch({
313 type: "thread.activity.append",331 type: "thread.activity.append",
314 commandId: serverCommandId("checkpoint-captured-activity"),332 commandId: yield* serverCommandId("checkpoint-captured-activity"),
315 threadId: input.threadId,333 threadId: input.threadId,
316 activity: {334 activity: {
317 id: EventId.make(crypto.randomUUID()),335 id: EventId.make(yield* randomUUID),
318 tone: "info",336 tone: "info",
319 kind: "checkpoint.captured",337 kind: "checkpoint.captured",
320 summary: "Checkpoint captured",338 summary: "Checkpoint captured",
...@@ -697,7 +715,7 @@ const make = Effect.gen(function* () {...@@ -697,7 +715,7 @@ const make = Effect.gen(function* () {
697 yield* orchestrationEngine715 yield* orchestrationEngine
698 .dispatch({716 .dispatch({
699 type: "thread.revert.complete",717 type: "thread.revert.complete",
700 commandId: serverCommandId("checkpoint-revert-complete"),718 commandId: yield* serverCommandId("checkpoint-revert-complete"),
701 threadId: event.payload.threadId,719 threadId: event.payload.threadId,
702 turnCount: event.payload.turnCount,720 turnCount: event.payload.turnCount,
703 createdAt: now,721 createdAt: now,
...@@ -787,7 +805,11 @@ const make = Effect.gen(function* () {...@@ -787,7 +805,11 @@ const make = Effect.gen(function* () {
787805
788 const processInput = (806 const processInput = (
789 input: ReactorInput,807 input: ReactorInput,
790 ): Effect.Effect<void, CheckpointStoreError | OrchestrationDispatchError, never> =>808 ): Effect.Effect<
809 void,
810 CheckpointStoreError | OrchestrationDispatchError | PlatformError.PlatformError,
811 never
812 > =>
791 input.source === "domain" ? processDomainEvent(input.event) : processRuntimeEvent(input.event);813 input.source === "domain" ? processDomainEvent(input.event) : processRuntimeEvent(input.event);
792814
793 const processInputSafely = (input: ReactorInput) =>815 const processInputSafely = (input: ReactorInput) =>
apps/server/src/orchestration/http.ts+4-2
...@@ -58,8 +58,10 @@ export const orchestrationSnapshotRouteLayer = HttpRouter.add(...@@ -58,8 +58,10 @@ export const orchestrationSnapshotRouteLayer = HttpRouter.add(
58 status: 200,58 status: 200,
59 });59 });
60 }).pipe(60 }).pipe(
61 Effect.catchTag("OrchestrationDispatchCommandError", respondToOrchestrationHttpError),61 Effect.catchTags({
62 Effect.catchTag("OrchestrationGetSnapshotError", respondToOrchestrationHttpError),62 OrchestrationDispatchCommandError: respondToOrchestrationHttpError,
63 OrchestrationGetSnapshotError: respondToOrchestrationHttpError,
64 }),
63 ),65 ),
64);66);
6567
apps/server/src/persistence/Layers/AuthSessions.ts+1-1
...@@ -40,7 +40,7 @@ const AuthSessionDbRow = Schema.Struct({...@@ -40,7 +40,7 @@ const AuthSessionDbRow = Schema.Struct({
40 revokedAt: Schema.NullOr(Schema.DateTimeUtcFromString),40 revokedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
41});41});
4242
43function toAuthSessionRecord(row: typeof AuthSessionDbRow.Type): typeof AuthSessionRecord.Type {43function toAuthSessionRecord(row: typeof AuthSessionDbRow.Type): AuthSessionRecord {
44 return {44 return {
45 sessionId: row.sessionId,45 sessionId: row.sessionId,
46 subject: row.subject,46 subject: row.subject,
apps/server/src/persistence/Migrations/009_ProviderSessionRuntimeMode.ts+1-3
...@@ -1,6 +1,4 @@...@@ -1,6 +1,4 @@
1import * as SqlClient from "effect/unstable/sql/SqlClient";1import * as SqlClient from "effect/unstable/sql/SqlClient";
2import * as Effect from "effect/Effect";2import * as Effect from "effect/Effect";
33
4export default Effect.gen(function* () {4export default Effect.asVoid(SqlClient.SqlClient);
5 yield* SqlClient.SqlClient;
6});
apps/server/src/process/externalLauncher.ts+1-1
...@@ -257,7 +257,7 @@ export interface ExternalLauncherShape {...@@ -257,7 +257,7 @@ export interface ExternalLauncherShape {
257 * ExternalLauncher - Service tag for browser/editor launch operations.257 * ExternalLauncher - Service tag for browser/editor launch operations.
258 */258 */
259export class ExternalLauncher extends Context.Service<ExternalLauncher, ExternalLauncherShape>()(259export class ExternalLauncher extends Context.Service<ExternalLauncher, ExternalLauncherShape>()(
260 "t3/process/ExternalLauncher",260 "t3/process/externalLauncher",
261) {}261) {}
262262
263// ==============================263// ==============================
apps/server/src/processRunner.ts+1-1
...@@ -90,7 +90,7 @@ export interface ProcessRunnerShape {...@@ -90,7 +90,7 @@ export interface ProcessRunnerShape {
90}90}
9191
92export class ProcessRunner extends Context.Service<ProcessRunner, ProcessRunnerShape>()(92export class ProcessRunner extends Context.Service<ProcessRunner, ProcessRunnerShape>()(
93 "t3/process/ProcessRunner",93 "t3/processRunner",
94) {}94) {}
9595
96const DEFAULT_TIMEOUT = "60 seconds";96const DEFAULT_TIMEOUT = "60 seconds";
apps/server/src/project/Services/ProjectSetupScriptRunner.ts+1-1
...@@ -41,4 +41,4 @@ export interface ProjectSetupScriptRunnerShape {...@@ -41,4 +41,4 @@ export interface ProjectSetupScriptRunnerShape {
41export class ProjectSetupScriptRunner extends Context.Service<41export class ProjectSetupScriptRunner extends Context.Service<
42 ProjectSetupScriptRunner,42 ProjectSetupScriptRunner,
43 ProjectSetupScriptRunnerShape43 ProjectSetupScriptRunnerShape
44>()("t3/project/ProjectSetupScriptRunner") {}44>()("t3/project/Services/ProjectSetupScriptRunner") {}
apps/server/src/provider/Layers/ClaudeAdapter.test.ts+1-1
...@@ -42,7 +42,7 @@ const decodeClaudeSettings = Schema.decodeSync(ClaudeSettings);...@@ -42,7 +42,7 @@ const decodeClaudeSettings = Schema.decodeSync(ClaudeSettings);
4242
43// Test-local service tag so the rest of the file can keep using `yield* ClaudeAdapter`.43// Test-local service tag so the rest of the file can keep using `yield* ClaudeAdapter`.
44class ClaudeAdapter extends Context.Service<ClaudeAdapter, ClaudeAdapterShape>()(44class ClaudeAdapter extends Context.Service<ClaudeAdapter, ClaudeAdapterShape>()(
45 "test/ClaudeAdapter",45 "t3/provider/Layers/ClaudeAdapter.test/ClaudeAdapter",
46) {}46) {}
4747
48class FakeClaudeQuery implements AsyncIterable<SDKMessage> {48class FakeClaudeQuery implements AsyncIterable<SDKMessage> {
apps/server/src/provider/Layers/CodexAdapter.test.ts+1-1
...@@ -50,7 +50,7 @@ const decodeCodexSettings = Schema.decodeSync(CodexSettings);...@@ -50,7 +50,7 @@ const decodeCodexSettings = Schema.decodeSync(CodexSettings);
5050
51// Test-local service tag so the rest of the file can keep using `yield* CodexAdapter`.51// Test-local service tag so the rest of the file can keep using `yield* CodexAdapter`.
52class CodexAdapter extends Context.Service<CodexAdapter, CodexAdapterShape>()(52class CodexAdapter extends Context.Service<CodexAdapter, CodexAdapterShape>()(
53 "test/CodexAdapter",53 "t3/provider/Layers/CodexAdapter.test/CodexAdapter",
54) {}54) {}
5555
56const asThreadId = (value: string): ThreadId => ThreadId.make(value);56const asThreadId = (value: string): ThreadId => ThreadId.make(value);
apps/server/src/provider/Layers/CursorAdapter.test.ts+1-1
...@@ -32,7 +32,7 @@ const decodeCursorSettings = Schema.decodeSync(CursorSettings);...@@ -32,7 +32,7 @@ const decodeCursorSettings = Schema.decodeSync(CursorSettings);
3232
33// Test-local service tag so the rest of the file can keep using `yield* CursorAdapter`.33// Test-local service tag so the rest of the file can keep using `yield* CursorAdapter`.
34class CursorAdapter extends Context.Service<CursorAdapter, CursorAdapterShape>()(34class CursorAdapter extends Context.Service<CursorAdapter, CursorAdapterShape>()(
35 "test/CursorAdapter",35 "t3/provider/Layers/CursorAdapter.test/CursorAdapter",
36) {}36) {}
3737
38const __dirname = path.dirname(fileURLToPath(import.meta.url));38const __dirname = path.dirname(fileURLToPath(import.meta.url));
apps/server/src/provider/Layers/CursorAdapter.ts+1-1
...@@ -97,7 +97,7 @@ export interface CursorAdapterLiveOptions {...@@ -97,7 +97,7 @@ export interface CursorAdapterLiveOptions {
97 * Selections are honored when `modelSelection.instanceId` matches this value.97 * Selections are honored when `modelSelection.instanceId` matches this value.
98 * Defaults to the legacy built-in instance id (`cursor`).98 * Defaults to the legacy built-in instance id (`cursor`).
99 */99 */
100 readonly instanceId?: typeof ProviderInstanceId.Type;100 readonly instanceId?: ProviderInstanceId;
101 /**101 /**
102 * Optional per-session settings resolver. When provided the adapter yields102 * Optional per-session settings resolver. When provided the adapter yields
103 * this effect at the start of every session and uses the result instead of103 * this effect at the start of every session and uses the result instead of
apps/server/src/provider/Layers/EventNdjsonLogger.ts+9-20
...@@ -14,6 +14,7 @@ import { RotatingFileSink } from "@t3tools/shared/logging";...@@ -14,6 +14,7 @@ import { RotatingFileSink } from "@t3tools/shared/logging";
14import * as Effect from "effect/Effect";14import * as Effect from "effect/Effect";
15import * as Exit from "effect/Exit";15import * as Exit from "effect/Exit";
16import * as Logger from "effect/Logger";16import * as Logger from "effect/Logger";
17import * as Schema from "effect/Schema";
17import * as Scope from "effect/Scope";18import * as Scope from "effect/Scope";
18import * as SynchronizedRef from "effect/SynchronizedRef";19import * as SynchronizedRef from "effect/SynchronizedRef";
1920
...@@ -24,6 +25,7 @@ const DEFAULT_MAX_FILES = 10;...@@ -24,6 +25,7 @@ const DEFAULT_MAX_FILES = 10;
24const DEFAULT_BATCH_WINDOW_MS = 200;25const DEFAULT_BATCH_WINDOW_MS = 200;
25const GLOBAL_THREAD_SEGMENT = "_global";26const GLOBAL_THREAD_SEGMENT = "_global";
26const LOG_SCOPE = "provider-observability";27const LOG_SCOPE = "provider-observability";
28const encodeUnknownJsonString = Schema.encodeUnknownEffect(Schema.UnknownFromJsonString);
2729
28export type EventNdjsonStream = "native" | "canonical" | "orchestration";30export type EventNdjsonStream = "native" | "canonical" | "orchestration";
2931
...@@ -87,26 +89,13 @@ function resolveStreamLabel(stream: EventNdjsonStream): string {...@@ -87,26 +89,13 @@ function resolveStreamLabel(stream: EventNdjsonStream): string {
87const toLogMessage = Effect.fn("toLogMessage")(function* (89const toLogMessage = Effect.fn("toLogMessage")(function* (
88 event: unknown,90 event: unknown,
89): Effect.fn.Return<string | undefined> {91): Effect.fn.Return<string | undefined> {
90 const serialized = yield* Effect.sync(() => {92 return yield* encodeUnknownJsonString(event).pipe(
91 try {93 Effect.catch((error) =>
92 return { ok: true as const, value: JSON.stringify(event) };94 logWarning("failed to serialize provider event log record", { error }).pipe(
93 } catch (error) {95 Effect.as(undefined),
94 return { ok: false as const, error };96 ),
95 }97 ),
96 });98 );
97
98 if (!serialized.ok) {
99 yield* logWarning("failed to serialize provider event log record", {
100 error: serialized.error,
101 });
102 return undefined;
103 }
104
105 if (typeof serialized.value !== "string") {
106 return undefined;
107 }
108
109 return serialized.value;
110});99});
111100
112const makeThreadWriter = Effect.fn("makeThreadWriter")(function* (input: {101const makeThreadWriter = Effect.fn("makeThreadWriter")(function* (input: {
apps/server/src/provider/Layers/OpenCodeAdapter.test.ts+1-1
...@@ -37,7 +37,7 @@ import {...@@ -37,7 +37,7 @@ import {
3737
38// Test-local service tag so the rest of the file can keep using `yield* OpenCodeAdapter`.38// Test-local service tag so the rest of the file can keep using `yield* OpenCodeAdapter`.
39class OpenCodeAdapter extends Context.Service<OpenCodeAdapter, OpenCodeAdapterShape>()(39class OpenCodeAdapter extends Context.Service<OpenCodeAdapter, OpenCodeAdapterShape>()(
40 "test/OpenCodeAdapter",40 "t3/provider/Layers/OpenCodeAdapter.test/OpenCodeAdapter",
41) {}41) {}
4242
43const asThreadId = (value: string): ThreadId => ThreadId.make(value);43const asThreadId = (value: string): ThreadId => ThreadId.make(value);
apps/server/src/provider/Layers/OpenCodeProvider.ts+19-29
...@@ -408,35 +408,25 @@ export const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatu...@@ -408,35 +408,25 @@ export const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatu
408 const inventoryExit = yield* Effect.exit(408 const inventoryExit = yield* Effect.exit(
409 Effect.scoped(409 Effect.scoped(
410 Effect.gen(function* () {410 Effect.gen(function* () {
411 const server = yield* openCodeRuntime411 const server = yield* openCodeRuntime.connectToOpenCodeServer({
412 .connectToOpenCodeServer({412 binaryPath: openCodeSettings.binaryPath,
413 binaryPath: openCodeSettings.binaryPath,413 serverUrl: openCodeSettings.serverUrl,
414 serverUrl: openCodeSettings.serverUrl,414 environment,
415 environment,415 });
416 })416 return yield* openCodeRuntime.loadOpenCodeInventory(
417 .pipe(417 openCodeRuntime.createOpenCodeSdkClient({
418 Effect.mapError(418 baseUrl: server.url,
419 (cause) =>419 directory: cwd,
420 new OpenCodeProbeError({ cause, detail: openCodeRuntimeErrorDetail(cause) }),420 ...(isExternalServer && openCodeSettings.serverPassword
421 ),421 ? { serverPassword: openCodeSettings.serverPassword }
422 );422 : {}),
423 return yield* openCodeRuntime423 }),
424 .loadOpenCodeInventory(424 );
425 openCodeRuntime.createOpenCodeSdkClient({425 }).pipe(
426 baseUrl: server.url,426 Effect.mapError(
427 directory: cwd,427 (cause) => new OpenCodeProbeError({ cause, detail: openCodeRuntimeErrorDetail(cause) }),
428 ...(isExternalServer && openCodeSettings.serverPassword428 ),
429 ? { serverPassword: openCodeSettings.serverPassword }429 ),
430 : {}),
431 }),
432 )
433 .pipe(
434 Effect.mapError(
435 (cause) =>
436 new OpenCodeProbeError({ cause, detail: openCodeRuntimeErrorDetail(cause) }),
437 ),
438 );
439 }),
440 ),430 ),
441 );431 );
442 if (inventoryExit._tag === "Failure") {432 if (inventoryExit._tag === "Failure") {
apps/server/src/provider/Layers/ProviderEventLoggers.ts+1-1
...@@ -50,7 +50,7 @@ export interface ProviderEventLoggersShape {...@@ -50,7 +50,7 @@ export interface ProviderEventLoggersShape {
50export class ProviderEventLoggers extends Context.Service<50export class ProviderEventLoggers extends Context.Service<
51 ProviderEventLoggers,51 ProviderEventLoggers,
52 ProviderEventLoggersShape52 ProviderEventLoggersShape
53>()("t3/provider/ProviderEventLoggers") {}53>()("t3/provider/Layers/ProviderEventLoggers") {}
5454
55/**55/**
56 * Constant value used by tests / boot layers that want to opt out of native56 * Constant value used by tests / boot layers that want to opt out of native
apps/server/src/provider/Layers/ProviderService.test.ts+2-6
...@@ -346,9 +346,7 @@ it.effect("ProviderServiceLive catches stopAll failures during shutdown", () =>...@@ -346,9 +346,7 @@ it.effect("ProviderServiceLive catches stopAll failures during shutdown", () =>
346 const scope = yield* Scope.make();346 const scope = yield* Scope.make();
347 const runtimeServices = yield* Layer.build(providerLayer).pipe(Scope.provide(scope));347 const runtimeServices = yield* Layer.build(providerLayer).pipe(Scope.provide(scope));
348348
349 yield* Effect.gen(function* () {349 yield* ProviderService.pipe(Effect.provide(runtimeServices));
350 yield* ProviderService;
351 }).pipe(Effect.provide(runtimeServices));
352 const closeExit = yield* Scope.close(scope, Exit.void).pipe(Effect.exit);350 const closeExit = yield* Scope.close(scope, Exit.void).pipe(Effect.exit);
353351
354 assert.equal(Exit.isSuccess(closeExit), true);352 assert.equal(Exit.isSuccess(closeExit), true);
...@@ -636,9 +634,7 @@ it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", (...@@ -636,9 +634,7 @@ it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", (
636 Layer.provide(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)),634 Layer.provide(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)),
637 );635 );
638636
639 yield* Effect.gen(function* () {637 yield* ProviderService.pipe(Effect.provide(providerLayer));
640 yield* ProviderService;
641 }).pipe(Effect.provide(providerLayer));
642638
643 const persistedProvider = yield* Effect.gen(function* () {639 const persistedProvider = yield* Effect.gen(function* () {
644 const directory = yield* ProviderSessionDirectory;640 const directory = yield* ProviderSessionDirectory;
apps/server/src/provider/opencodeRuntime.ts+1-1
...@@ -544,7 +544,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () {...@@ -544,7 +544,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () {
544});544});
545545
546export class OpenCodeRuntime extends Context.Service<OpenCodeRuntime, OpenCodeRuntimeShape>()(546export class OpenCodeRuntime extends Context.Service<OpenCodeRuntime, OpenCodeRuntimeShape>()(
547 "t3/provider/OpenCodeRuntime",547 "t3/provider/opencodeRuntime",
548) {}548) {}
549549
550export const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(550export const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(
apps/server/src/provider/providerMaintenanceRunner.ts+1-1
...@@ -53,7 +53,7 @@ export interface ProviderMaintenanceRunnerShape {...@@ -53,7 +53,7 @@ export interface ProviderMaintenanceRunnerShape {
53export class ProviderMaintenanceRunner extends Context.Service<53export class ProviderMaintenanceRunner extends Context.Service<
54 ProviderMaintenanceRunner,54 ProviderMaintenanceRunner,
55 ProviderMaintenanceRunnerShape55 ProviderMaintenanceRunnerShape
56>()("t3/provider/ProviderMaintenanceRunner") {}56>()("t3/provider/providerMaintenanceRunner") {}
5757
58class ProviderMaintenanceCommandError extends Data.TaggedError("ProviderMaintenanceCommandError")<{58class ProviderMaintenanceCommandError extends Data.TaggedError("ProviderMaintenanceCommandError")<{
59 readonly message: string;59 readonly message: string;
apps/server/src/server.test.ts+126-221
...@@ -40,6 +40,7 @@ import * as Path from "effect/Path";...@@ -40,6 +40,7 @@ import * as Path from "effect/Path";
40import * as Stream from "effect/Stream";40import * as Stream from "effect/Stream";
41import { ChildProcessSpawner } from "effect/unstable/process";41import { ChildProcessSpawner } from "effect/unstable/process";
42import {42import {
43 Cookies,
43 FetchHttpClient,44 FetchHttpClient,
44 HttpBody,45 HttpBody,
45 HttpClient,46 HttpClient,
...@@ -780,13 +781,6 @@ const appendSessionCookieToWsUrl = (url: string, sessionCookieHeader: string) =>...@@ -780,13 +781,6 @@ const appendSessionCookieToWsUrl = (url: string, sessionCookieHeader: string) =>
780 return isAbsoluteUrl ? next.toString() : `${next.pathname}${next.search}${next.hash}`;781 return isAbsoluteUrl ? next.toString() : `${next.pathname}${next.search}${next.hash}`;
781};782};
782783
783const getHttpServerUrl = (pathname = "") =>
784 Effect.gen(function* () {
785 const server = yield* HttpServer.HttpServer;
786 const address = server.address as HttpServer.TcpAddress;
787 return `http://127.0.0.1:${address.port}${pathname}`;
788 });
789
790const bootstrapBrowserSession = (784const bootstrapBrowserSession = (
791 credential = defaultDesktopBootstrapToken,785 credential = defaultDesktopBootstrapToken,
792 options?: {786 options?: {
...@@ -794,20 +788,11 @@ const bootstrapBrowserSession = (...@@ -794,20 +788,11 @@ const bootstrapBrowserSession = (
794 },788 },
795) =>789) =>
796 Effect.gen(function* () {790 Effect.gen(function* () {
797 const bootstrapUrl = yield* getHttpServerUrl("/api/auth/bootstrap");791 const response = yield* HttpClient.post("/api/auth/bootstrap", {
798 const response = yield* Effect.promise(() =>792 headers: options?.headers,
799 fetch(bootstrapUrl, {793 body: yield* HttpBody.json({ credential }),
800 method: "POST",794 });
801 headers: {795 const body = (yield* response.json) as {
802 "content-type": "application/json",
803 ...options?.headers,
804 },
805 body: JSON.stringify({
806 credential,
807 }),
808 }),
809 );
810 const body = (yield* Effect.promise(() => response.json())) as {
811 readonly authenticated: boolean;796 readonly authenticated: boolean;
812 readonly sessionMethod: string;797 readonly sessionMethod: string;
813 readonly expiresAt: string;798 readonly expiresAt: string;
...@@ -815,7 +800,7 @@ const bootstrapBrowserSession = (...@@ -815,7 +800,7 @@ const bootstrapBrowserSession = (
815 return {800 return {
816 response,801 response,
817 body,802 body,
818 cookie: response.headers.get("set-cookie"),803 cookie: Cookies.toSetCookieHeaders(response.cookies)[0] ?? null,
819 };804 };
820 });805 });
821806
...@@ -826,20 +811,11 @@ const bootstrapBearerSession = (...@@ -826,20 +811,11 @@ const bootstrapBearerSession = (
826 },811 },
827) =>812) =>
828 Effect.gen(function* () {813 Effect.gen(function* () {
829 const bootstrapUrl = yield* getHttpServerUrl("/api/auth/bootstrap/bearer");814 const response = yield* HttpClient.post("/api/auth/bootstrap/bearer", {
830 const response = yield* Effect.promise(() =>815 headers: options?.headers,
831 fetch(bootstrapUrl, {816 body: yield* HttpBody.json({ credential }),
832 method: "POST",817 });
833 headers: {818 const body = (yield* response.json) as {
834 "content-type": "application/json",
835 ...options?.headers,
836 },
837 body: JSON.stringify({
838 credential,
839 }),
840 }),
841 );
842 const body = (yield* Effect.promise(() => response.json())) as {
843 readonly authenticated: boolean;819 readonly authenticated: boolean;
844 readonly sessionMethod: string;820 readonly sessionMethod: string;
845 readonly expiresAt: string;821 readonly expiresAt: string;
...@@ -859,7 +835,7 @@ class AuthenticationGetterError extends Data.TaggedError("AuthenticationGetterEr...@@ -859,7 +835,7 @@ class AuthenticationGetterError extends Data.TaggedError("AuthenticationGetterEr
859const getAuthenticatedSessionCookieHeader = (credential = defaultDesktopBootstrapToken) =>835const getAuthenticatedSessionCookieHeader = (credential = defaultDesktopBootstrapToken) =>
860 Effect.gen(function* () {836 Effect.gen(function* () {
861 const { response, cookie } = yield* bootstrapBrowserSession(credential);837 const { response, cookie } = yield* bootstrapBrowserSession(credential);
862 if (!response.ok) {838 if (response.status !== 200) {
863 return yield* new AuthenticationGetterError({839 return yield* new AuthenticationGetterError({
864 message: `Expected bootstrap session response to succeed, got ${response.status}`,840 message: `Expected bootstrap session response to succeed, got ${response.status}`,
865 });841 });
...@@ -877,7 +853,7 @@ const getAuthenticatedSessionCookieHeader = (credential = defaultDesktopBootstra...@@ -877,7 +853,7 @@ const getAuthenticatedSessionCookieHeader = (credential = defaultDesktopBootstra
877const getAuthenticatedBearerSessionToken = (credential = defaultDesktopBootstrapToken) =>853const getAuthenticatedBearerSessionToken = (credential = defaultDesktopBootstrapToken) =>
878 Effect.gen(function* () {854 Effect.gen(function* () {
879 const { response, body } = yield* bootstrapBearerSession(credential);855 const { response, body } = yield* bootstrapBearerSession(credential);
880 if (!response.ok) {856 if (response.status !== 200) {
881 return yield* new AuthenticationGetterError({857 return yield* new AuthenticationGetterError({
882 message: `Expected bearer bootstrap response to succeed, got ${response.status}`,858 message: `Expected bearer bootstrap response to succeed, got ${response.status}`,
883 });859 });
...@@ -908,14 +884,14 @@ const splitHeaderTokens = (value: string | null) =>...@@ -908,14 +884,14 @@ const splitHeaderTokens = (value: string | null) =>
908 .filter((token) => token.length > 0)884 .filter((token) => token.length > 0)
909 .toSorted();885 .toSorted();
910886
911const assertBrowserApiCorsHeaders = (headers: Headers) => {887const assertBrowserApiCorsHeaders = (headers: Readonly<Record<string, string | undefined>>) => {
912 assert.equal(headers.get("access-control-allow-origin"), "*");888 assert.equal(headers["access-control-allow-origin"], "*");
913 assert.deepEqual(splitHeaderTokens(headers.get("access-control-allow-methods")), [889 assert.deepEqual(splitHeaderTokens(headers["access-control-allow-methods"] ?? null), [
914 "GET",890 "GET",
915 "OPTIONS",891 "OPTIONS",
916 "POST",892 "POST",
917 ]);893 ]);
918 assert.deepEqual(splitHeaderTokens(headers.get("access-control-allow-headers")), [894 assert.deepEqual(splitHeaderTokens(headers["access-control-allow-headers"] ?? null), [
919 "authorization",895 "authorization",
920 "b3",896 "b3",
921 "content-type",897 "content-type",
...@@ -964,14 +940,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -964,14 +940,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
964 config: { devUrl: new URL("http://127.0.0.1:5173") },940 config: { devUrl: new URL("http://127.0.0.1:5173") },
965 });941 });
966942
967 const url = yield* getHttpServerUrl("/foo/bar?token=test-token");943 const response = yield* HttpClient.get("/foo/bar?token=test-token").pipe(
968 const response = yield* Effect.promise(() => fetch(url, { redirect: "manual" }));944 Effect.provideService(FetchHttpClient.RequestInit, { redirect: "manual" }),
945 );
969946
970 assert.equal(response.status, 302);947 assert.equal(response.status, 302);
971 assert.equal(948 assert.equal(response.headers.location, "http://127.0.0.1:5173/foo/bar?token=test-token");
972 response.headers.get("location"),
973 "http://127.0.0.1:5173/foo/bar?token=test-token",
974 );
975 }).pipe(Effect.provide(NodeHttpServer.layerTest)),949 }).pipe(Effect.provide(NodeHttpServer.layerTest)),
976 );950 );
977951
...@@ -1034,11 +1008,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1034,11 +1008,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1034 Effect.gen(function* () {1008 Effect.gen(function* () {
1035 yield* buildAppUnderTest();1009 yield* buildAppUnderTest();
10361010
1037 const url = yield* getHttpServerUrl("/.well-known/t3/environment");1011 const response = yield* HttpClient.get("/.well-known/t3/environment");
1038 const response = yield* Effect.promise(() => fetch(url));1012 const body = (yield* response.json) as typeof testEnvironmentDescriptor;
1039 const body = (yield* Effect.promise(() =>
1040 response.json(),
1041 )) as typeof testEnvironmentDescriptor;
10421013
1043 assert.equal(response.status, 200);1014 assert.equal(response.status, 200);
1044 assert.deepEqual(body, testEnvironmentDescriptor);1015 assert.deepEqual(body, testEnvironmentDescriptor);
...@@ -1049,17 +1020,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1049,17 +1020,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1049 Effect.gen(function* () {1020 Effect.gen(function* () {
1050 yield* buildAppUnderTest();1021 yield* buildAppUnderTest();
10511022
1052 const url = yield* getHttpServerUrl("/.well-known/t3/environment");1023 const response = yield* HttpClient.get("/.well-known/t3/environment", {
1053 const response = yield* Effect.promise(() =>1024 headers: {
1054 fetch(url, {1025 origin: crossOriginClientOrigin,
1055 headers: {1026 },
1056 origin: crossOriginClientOrigin,1027 });
1057 },1028 const body = (yield* response.json) as typeof testEnvironmentDescriptor;
1058 }),
1059 );
1060 const body = (yield* Effect.promise(() =>
1061 response.json(),
1062 )) as typeof testEnvironmentDescriptor;
10631029
1064 assert.equal(response.status, 200);1030 assert.equal(response.status, 200);
1065 assertBrowserApiCorsHeaders(response.headers);1031 assertBrowserApiCorsHeaders(response.headers);
...@@ -1071,9 +1037,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1071,9 +1037,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1071 Effect.gen(function* () {1037 Effect.gen(function* () {
1072 yield* buildAppUnderTest();1038 yield* buildAppUnderTest();
10731039
1074 const url = yield* getHttpServerUrl("/api/auth/session");1040 const response = yield* HttpClient.get("/api/auth/session");
1075 const response = yield* Effect.promise(() => fetch(url));1041 const body = (yield* response.json) as {
1076 const body = (yield* Effect.promise(() => response.json())) as {
1077 readonly authenticated: boolean;1042 readonly authenticated: boolean;
1078 readonly auth: {1043 readonly auth: {
1079 readonly policy: string;1044 readonly policy: string;
...@@ -1111,15 +1076,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1111,15 +1076,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1111 assert.isUndefined((bootstrapBody as { readonly sessionToken?: string }).sessionToken);1076 assert.isUndefined((bootstrapBody as { readonly sessionToken?: string }).sessionToken);
1112 assert.isDefined(setCookie);1077 assert.isDefined(setCookie);
11131078
1114 const sessionUrl = yield* getHttpServerUrl("/api/auth/session");1079 const sessionResponse = yield* HttpClient.get("/api/auth/session", {
1115 const sessionResponse = yield* Effect.promise(() =>1080 headers: {
1116 fetch(sessionUrl, {1081 cookie: setCookie?.split(";")[0] ?? "",
1117 headers: {1082 },
1118 cookie: setCookie?.split(";")[0] ?? "",1083 });
1119 },1084 const sessionBody = (yield* sessionResponse.json) as {
1120 }),
1121 );
1122 const sessionBody = (yield* Effect.promise(() => sessionResponse.json())) as {
1123 readonly authenticated: boolean;1085 readonly authenticated: boolean;
1124 readonly sessionMethod?: string;1086 readonly sessionMethod?: string;
1125 };1087 };
...@@ -1145,15 +1107,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1145,15 +1107,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1145 assert.equal(typeof bootstrapBody.sessionToken, "string");1107 assert.equal(typeof bootstrapBody.sessionToken, "string");
1146 assert.isTrue((bootstrapBody.sessionToken?.length ?? 0) > 0);1108 assert.isTrue((bootstrapBody.sessionToken?.length ?? 0) > 0);
11471109
1148 const sessionUrl = yield* getHttpServerUrl("/api/auth/session");1110 const sessionResponse = yield* HttpClient.get("/api/auth/session", {
1149 const sessionResponse = yield* Effect.promise(() =>1111 headers: {
1150 fetch(sessionUrl, {1112 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,
1151 headers: {1113 },
1152 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,1114 });
1153 },1115 const sessionBody = (yield* sessionResponse.json) as {
1154 }),
1155 );
1156 const sessionBody = (yield* Effect.promise(() => sessionResponse.json())) as {
1157 readonly authenticated: boolean;1116 readonly authenticated: boolean;
1158 readonly sessionMethod?: string;1117 readonly sessionMethod?: string;
1159 };1118 };
...@@ -1169,16 +1128,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1169,16 +1128,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1169 yield* buildAppUnderTest();1128 yield* buildAppUnderTest();
11701129
1171 const bearerToken = yield* getAuthenticatedBearerSessionToken();1130 const bearerToken = yield* getAuthenticatedBearerSessionToken();
1172 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");1131 const wsTokenResponse = yield* HttpClient.post("/api/auth/ws-token", {
1173 const wsTokenResponse = yield* Effect.promise(() =>1132 headers: {
1174 fetch(wsTokenUrl, {1133 authorization: `Bearer ${bearerToken}`,
1175 method: "POST",1134 },
1176 headers: {1135 });
1177 authorization: `Bearer ${bearerToken}`,1136 const wsTokenBody = (yield* wsTokenResponse.json) as {
1178 },
1179 }),
1180 );
1181 const wsTokenBody = (yield* Effect.promise(() => wsTokenResponse.json())) as {
1182 readonly token: string;1137 readonly token: string;
1183 readonly expiresAt: string;1138 readonly expiresAt: string;
1184 };1139 };
...@@ -1207,16 +1162,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1207,16 +1162,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1207 assert.equal(bootstrapBody.authenticated, true);1162 assert.equal(bootstrapBody.authenticated, true);
1208 assert.equal(typeof bootstrapBody.sessionToken, "string");1163 assert.equal(typeof bootstrapBody.sessionToken, "string");
12091164
1210 const sessionUrl = yield* getHttpServerUrl("/api/auth/session");1165 const sessionResponse = yield* HttpClient.get("/api/auth/session", {
1211 const sessionResponse = yield* Effect.promise(() =>1166 headers: {
1212 fetch(sessionUrl, {1167 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,
1213 headers: {1168 origin,
1214 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,1169 },
1215 origin,1170 });
1216 },1171 const sessionBody = (yield* sessionResponse.json) as {
1217 }),
1218 );
1219 const sessionBody = (yield* Effect.promise(() => sessionResponse.json())) as {
1220 readonly authenticated: boolean;1172 readonly authenticated: boolean;
1221 readonly sessionMethod?: string;1173 readonly sessionMethod?: string;
1222 };1174 };
...@@ -1226,17 +1178,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1226,17 +1178,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1226 assert.equal(sessionBody.authenticated, true);1178 assert.equal(sessionBody.authenticated, true);
1227 assert.equal(sessionBody.sessionMethod, "bearer-session-token");1179 assert.equal(sessionBody.sessionMethod, "bearer-session-token");
12281180
1229 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");1181 const wsTokenResponse = yield* HttpClient.post("/api/auth/ws-token", {
1230 const wsTokenResponse = yield* Effect.promise(() =>1182 headers: {
1231 fetch(wsTokenUrl, {1183 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,
1232 method: "POST",1184 origin,
1233 headers: {1185 },
1234 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,1186 });
1235 origin,1187 const wsTokenBody = (yield* wsTokenResponse.json) as {
1236 },
1237 }),
1238 );
1239 const wsTokenBody = (yield* Effect.promise(() => wsTokenResponse.json())) as {
1240 readonly token: string;1188 readonly token: string;
1241 };1189 };
12421190
...@@ -1252,17 +1200,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1252,17 +1200,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1252 Effect.gen(function* () {1200 Effect.gen(function* () {
1253 yield* buildAppUnderTest();1201 yield* buildAppUnderTest();
12541202
1255 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");1203 const response = yield* HttpClient.options("/api/auth/ws-token", {
1256 const response = yield* Effect.promise(() =>1204 headers: {
1257 fetch(wsTokenUrl, {1205 origin: crossOriginClientOrigin,
1258 method: "OPTIONS",1206 "access-control-request-method": "POST",
1259 headers: {1207 "access-control-request-headers": "authorization",
1260 origin: crossOriginClientOrigin,1208 },
1261 "access-control-request-method": "POST",1209 });
1262 "access-control-request-headers": "authorization",
1263 },
1264 }),
1265 );
12661210
1267 assert.equal(response.status, 204);1211 assert.equal(response.status, 204);
1268 assertBrowserApiCorsHeaders(response.headers);1212 assertBrowserApiCorsHeaders(response.headers);
...@@ -1273,16 +1217,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1273,16 +1217,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1273 Effect.gen(function* () {1217 Effect.gen(function* () {
1274 yield* buildAppUnderTest();1218 yield* buildAppUnderTest();
12751219
1276 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");1220 const response = yield* HttpClient.post("/api/auth/ws-token", {
1277 const response = yield* Effect.promise(() =>1221 headers: {
1278 fetch(wsTokenUrl, {1222 origin: crossOriginClientOrigin,
1279 method: "POST",1223 },
1280 headers: {1224 });
1281 origin: crossOriginClientOrigin,1225 const body = (yield* response.json) as {
1282 },
1283 }),
1284 );
1285 const body = (yield* Effect.promise(() => response.json())) as {
1286 readonly error?: string;1226 readonly error?: string;
1287 };1227 };
12881228
...@@ -1357,17 +1297,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1357,17 +1297,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1357 readonly credential: string;1297 readonly credential: string;
1358 }>;1298 }>;
13591299
1360 const revokeUrl = yield* getHttpServerUrl("/api/auth/pairing-links/revoke");1300 const revokeResponse = yield* HttpClient.post("/api/auth/pairing-links/revoke", {
1361 const revokeResponse = yield* Effect.promise(() =>1301 headers: {
1362 fetch(revokeUrl, {1302 cookie: ownerCookie,
1363 method: "POST",1303 },
1364 headers: {1304 body: yield* HttpBody.json({ id: createdBody.id }),
1365 cookie: ownerCookie,1305 });
1366 "content-type": "application/json",
1367 },
1368 body: JSON.stringify({ id: createdBody.id }),
1369 }),
1370 );
1371 const revokedBootstrap = yield* bootstrapBrowserSession(createdBody.credential);1306 const revokedBootstrap = yield* bootstrapBrowserSession(createdBody.credential);
13721307
1373 assert.equal(createdResponse.status, 200);1308 assert.equal(createdResponse.status, 200);
...@@ -1420,20 +1355,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1420,20 +1355,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1420 });1355 });
14211356
1422 const ownerCookie = yield* getAuthenticatedSessionCookieHeader();1357 const ownerCookie = yield* getAuthenticatedSessionCookieHeader();
1423 const pairingTokenUrl = yield* getHttpServerUrl("/api/auth/pairing-token");1358 const ownerPairingResponse = yield* HttpClient.post("/api/auth/pairing-token", {
1424 const ownerPairingResponse = yield* Effect.promise(() =>1359 headers: {
1425 fetch(pairingTokenUrl, {1360 cookie: ownerCookie,
1426 method: "POST",1361 },
1427 headers: {1362 body: yield* HttpBody.json({ label: "Julius iPhone" }),
1428 cookie: ownerCookie,1363 });
1429 "content-type": "application/json",1364 const ownerPairingBody = (yield* ownerPairingResponse.json) as {
1430 },
1431 body: JSON.stringify({
1432 label: "Julius iPhone",
1433 }),
1434 }),
1435 );
1436 const ownerPairingBody = (yield* Effect.promise(() => ownerPairingResponse.json())) as {
1437 readonly credential: string;1365 readonly credential: string;
1438 readonly label?: string;1366 readonly label?: string;
1439 };1367 };
...@@ -1448,17 +1376,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1448,17 +1376,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1448 assert.isDefined(pairedSessionCookie);1376 assert.isDefined(pairedSessionCookie);
14491377
1450 const pairedSessionCookieHeader = pairedSessionCookie ?? "";1378 const pairedSessionCookieHeader = pairedSessionCookie ?? "";
1451 const listClientsUrl = yield* getHttpServerUrl("/api/auth/clients");1379 const listBeforeResponse = yield* HttpClient.get("/api/auth/clients", {
1452 const listBeforeResponse = yield* Effect.promise(() =>1380 headers: {
1453 fetch(listClientsUrl, {1381 cookie: ownerCookie,
1454 headers: {1382 },
1455 cookie: ownerCookie,1383 });
1456 },1384 const clientsBefore = (yield* listBeforeResponse.json) as ReadonlyArray<{
1457 }),
1458 );
1459 const clientsBefore = (yield* Effect.promise(() =>
1460 listBeforeResponse.json(),
1461 )) as ReadonlyArray<{
1462 readonly sessionId: string;1385 readonly sessionId: string;
1463 readonly current: boolean;1386 readonly current: boolean;
1464 readonly client: {1387 readonly client: {
...@@ -1555,17 +1478,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1555,17 +1478,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1555 const pairedSessionId = clients.find((entry) => !entry.current)?.sessionId;1478 const pairedSessionId = clients.find((entry) => !entry.current)?.sessionId;
1556 assert.isDefined(pairedSessionId);1479 assert.isDefined(pairedSessionId);
15571480
1558 const revokeUrl = yield* getHttpServerUrl("/api/auth/clients/revoke");1481 const revokeResponse = yield* HttpClient.post("/api/auth/clients/revoke", {
1559 const revokeResponse = yield* Effect.promise(() =>1482 headers: {
1560 fetch(revokeUrl, {1483 cookie: ownerCookie,
1561 method: "POST",1484 },
1562 headers: {1485 body: yield* HttpBody.json({ sessionId: pairedSessionId }),
1563 cookie: ownerCookie,1486 });
1564 "content-type": "application/json",
1565 },
1566 body: JSON.stringify({ sessionId: pairedSessionId }),
1567 }),
1568 );
1569 const pairedClientPairingResponse = yield* HttpClient.post("/api/auth/pairing-token", {1487 const pairedClientPairingResponse = yield* HttpClient.post("/api/auth/pairing-token", {
1570 headers: {1488 headers: {
1571 cookie: pairedSessionCookie,1489 cookie: pairedSessionCookie,
...@@ -1665,16 +1583,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1665,16 +1583,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1665 yield* buildAppUnderTest();1583 yield* buildAppUnderTest();
16661584
1667 const bearerToken = yield* getAuthenticatedBearerSessionToken();1585 const bearerToken = yield* getAuthenticatedBearerSessionToken();
1668 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");1586 const wsTokenResponse = yield* HttpClient.post("/api/auth/ws-token", {
1669 const wsTokenResponse = yield* Effect.promise(() =>1587 headers: {
1670 fetch(wsTokenUrl, {1588 authorization: `Bearer ${bearerToken}`,
1671 method: "POST",1589 },
1672 headers: {1590 });
1673 authorization: `Bearer ${bearerToken}`,1591 const wsTokenBody = (yield* wsTokenResponse.json) as {
1674 },
1675 }),
1676 );
1677 const wsTokenBody = (yield* Effect.promise(() => wsTokenResponse.json())) as {
1678 readonly token: string;1592 readonly token: string;
1679 };1593 };
1680 const wsUrl = `${yield* getWsServerUrl("/ws", { authenticated: false })}?wsToken=${encodeURIComponent(wsTokenBody.token)}`;1594 const wsUrl = `${yield* getWsServerUrl("/ws", { authenticated: false })}?wsToken=${encodeURIComponent(wsTokenBody.token)}`;
...@@ -1876,8 +1790,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1876,8 +1790,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1876 "content-type": "application/json",1790 "content-type": "application/json",
1877 origin: "http://localhost:5733",1791 origin: "http://localhost:5733",
1878 },1792 },
1879 // @effect-diagnostics-next-line preferSchemaOverJson:off1793 body: yield* HttpBody.json(payload),
1880 body: HttpBody.text(JSON.stringify(payload), "application/json"),
1881 });1794 });
18821795
1883 assert.equal(response.status, 204);1796 assert.equal(response.status, 204);
...@@ -1934,31 +1847,24 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1934,31 +1847,24 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1934 Effect.gen(function* () {1847 Effect.gen(function* () {
1935 yield* buildAppUnderTest();1848 yield* buildAppUnderTest();
19361849
1937 const url = yield* getHttpServerUrl("/api/observability/v1/traces");1850 const response = yield* HttpClient.options("/api/observability/v1/traces", {
1938 const response = yield* Effect.promise(() =>1851 headers: {
1939 fetch(url, {1852 origin: "http://localhost:5733",
1940 method: "OPTIONS",1853 "access-control-request-method": "POST",
1941 headers: {1854 "access-control-request-headers": "content-type",
1942 origin: "http://localhost:5733",1855 },
1943 "access-control-request-method": "POST",1856 });
1944 "access-control-request-headers": "content-type",
1945 },
1946 }),
1947 );
19481857
1949 assert.equal(response.status, 204);1858 assert.equal(response.status, 204);
1950 assert.equal(response.headers.get("access-control-allow-origin"), "*");1859 assert.equal(response.headers["access-control-allow-origin"], "*");
1951 assert.deepEqual(splitHeaderTokens(response.headers.get("access-control-allow-methods")), [1860 assert.deepEqual(
1952 "GET",1861 splitHeaderTokens(response.headers["access-control-allow-methods"] ?? null),
1953 "OPTIONS",1862 ["GET", "OPTIONS", "POST"],
1954 "POST",1863 );
1955 ]);1864 assert.deepEqual(
1956 assert.deepEqual(splitHeaderTokens(response.headers.get("access-control-allow-headers")), [1865 splitHeaderTokens(response.headers["access-control-allow-headers"] ?? null),
1957 "authorization",1866 ["authorization", "b3", "content-type", "traceparent"],
1958 "b3",1867 );
1959 "content-type",
1960 "traceparent",
1961 ]);
1962 }).pipe(Effect.provide(NodeHttpServer.layerTest)),1868 }).pipe(Effect.provide(NodeHttpServer.layerTest)),
1963 );1869 );
19641870
...@@ -1995,8 +1901,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {...@@ -1995,8 +1901,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
1995 cookie: yield* getAuthenticatedSessionCookieHeader(),1901 cookie: yield* getAuthenticatedSessionCookieHeader(),
1996 "content-type": "application/json",1902 "content-type": "application/json",
1997 },1903 },
1998 // @effect-diagnostics-next-line preferSchemaOverJson:off1904 body: yield* HttpBody.json(payload),
1999 body: HttpBody.text(JSON.stringify(payload), "application/json"),
2000 });1905 });
20011906
2002 assert.equal(response.status, 204);1907 assert.equal(response.status, 204);
apps/server/src/serverRuntimeStartup.test.ts+53
...@@ -1,10 +1,12 @@...@@ -1,10 +1,12 @@
1import * as NodeServices from "@effect/platform-node/NodeServices";1import * as NodeServices from "@effect/platform-node/NodeServices";
2import { DEFAULT_MODEL, ProjectId, ProviderInstanceId, ThreadId } from "@t3tools/contracts";2import { DEFAULT_MODEL, ProjectId, ProviderInstanceId, ThreadId } from "@t3tools/contracts";
3import { assert, it } from "@effect/vitest";3import { assert, it } from "@effect/vitest";
4import * as Crypto from "effect/Crypto";
4import * as Deferred from "effect/Deferred";5import * as Deferred from "effect/Deferred";
5import * as Effect from "effect/Effect";6import * as Effect from "effect/Effect";
6import * as Fiber from "effect/Fiber";7import * as Fiber from "effect/Fiber";
7import * as Option from "effect/Option";8import * as Option from "effect/Option";
9import * as PlatformError from "effect/PlatformError";
8import * as Ref from "effect/Ref";10import * as Ref from "effect/Ref";
9import * as Stream from "effect/Stream";11import * as Stream from "effect/Stream";
1012
...@@ -222,3 +224,54 @@ it.effect("resolveAutoBootstrapWelcomeTargets creates a project and thread when...@@ -222,3 +224,54 @@ it.effect("resolveAutoBootstrapWelcomeTargets creates a project and thread when
222 assert.deepStrictEqual(yield* Ref.get(dispatchCalls), ["project.create", "thread.create"]);224 assert.deepStrictEqual(yield* Ref.get(dispatchCalls), ["project.create", "thread.create"]);
223 }),225 }),
224);226);
227
228it.effect("resolveAutoBootstrapWelcomeTargets preserves typed UUID generation failures", () =>
229 Effect.gen(function* () {
230 const crypto = yield* Crypto.Crypto;
231 const uuidError = PlatformError.systemError({
232 _tag: "Unknown",
233 module: "Crypto",
234 method: "randomUUIDv4",
235 description: "UUID generation unavailable",
236 });
237 const dispatchCalls = yield* Ref.make<ReadonlyArray<string>>([]);
238
239 const error = yield* resolveAutoBootstrapWelcomeTargets.pipe(
240 Effect.provideService(ServerConfig, {
241 cwd: "/tmp/startup-project",
242 autoBootstrapProjectFromCwd: true,
243 } as never),
244 Effect.provideService(ProjectionSnapshotQuery, {
245 getCommandReadModel: () => Effect.die("unused"),
246 getSnapshot: () => Effect.die("unused"),
247 getShellSnapshot: () => Effect.die("unused"),
248 getArchivedShellSnapshot: () => Effect.die("unused"),
249 getSnapshotSequence: () => Effect.die("unused"),
250 getCounts: () => Effect.die("unused"),
251 getActiveProjectByWorkspaceRoot: () => Effect.succeed(Option.none()),
252 getProjectShellById: () => Effect.die("unused"),
253 getFirstActiveThreadIdByProjectId: () => Effect.succeed(Option.none()),
254 getThreadCheckpointContext: () => Effect.succeed(Option.none()),
255 getFullThreadDiffContext: () => Effect.succeed(Option.none()),
256 getThreadShellById: () => Effect.die("unused"),
257 getThreadDetailById: () => Effect.die("unused"),
258 }),
259 Effect.provideService(OrchestrationEngineService, {
260 readEvents: () => Stream.empty,
261 dispatch: (command) =>
262 Ref.update(dispatchCalls, (calls) => [...calls, command.type]).pipe(
263 Effect.as({ sequence: 1 }),
264 ),
265 streamDomainEvents: Stream.empty,
266 } satisfies OrchestrationEngineShape),
267 Effect.provideService(Crypto.Crypto, {
268 ...crypto,
269 randomUUIDv4: Effect.fail(uuidError),
270 }),
271 Effect.flip,
272 );
273
274 assert.strictEqual(error, uuidError);
275 assert.deepStrictEqual(yield* Ref.get(dispatchCalls), []);
276 }).pipe(Effect.provide(NodeServices.layer)),
277);
apps/server/src/serverRuntimeStartup.ts+7-4
...@@ -19,6 +19,7 @@ import * as Ref from "effect/Ref";...@@ -19,6 +19,7 @@ import * as Ref from "effect/Ref";
19import * as Scope from "effect/Scope";19import * as Scope from "effect/Scope";
20import * as Context from "effect/Context";20import * as Context from "effect/Context";
21import * as Console from "effect/Console";21import * as Console from "effect/Console";
22import * as Crypto from "effect/Crypto";
22import * as DateTime from "effect/DateTime";23import * as DateTime from "effect/DateTime";
2324
24import { ServerConfig } from "./config.ts";25import { ServerConfig } from "./config.ts";
...@@ -170,6 +171,8 @@ export const resolveWelcomeBase = Effect.gen(function* () {...@@ -170,6 +171,8 @@ export const resolveWelcomeBase = Effect.gen(function* () {
170});171});
171172
172export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {173export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {
174 const crypto = yield* Crypto.Crypto;
175 const randomUUID = crypto.randomUUIDv4;
173 const serverConfig = yield* ServerConfig;176 const serverConfig = yield* ServerConfig;
174 const projectionReadModelQuery = yield* ProjectionSnapshotQuery;177 const projectionReadModelQuery = yield* ProjectionSnapshotQuery;
175 const orchestrationEngine = yield* OrchestrationEngineService;178 const orchestrationEngine = yield* OrchestrationEngineService;
...@@ -188,12 +191,12 @@ export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {...@@ -188,12 +191,12 @@ export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {
188191
189 if (Option.isNone(existingProject)) {192 if (Option.isNone(existingProject)) {
190 const createdAt = DateTime.formatIso(yield* DateTime.now);193 const createdAt = DateTime.formatIso(yield* DateTime.now);
191 nextProjectId = ProjectId.make(crypto.randomUUID());194 nextProjectId = ProjectId.make(yield* randomUUID);
192 const bootstrapProjectTitle = path.basename(serverConfig.cwd) || "project";195 const bootstrapProjectTitle = path.basename(serverConfig.cwd) || "project";
193 nextProjectDefaultModelSelection = getAutoBootstrapDefaultModelSelection();196 nextProjectDefaultModelSelection = getAutoBootstrapDefaultModelSelection();
194 yield* orchestrationEngine.dispatch({197 yield* orchestrationEngine.dispatch({
195 type: "project.create",198 type: "project.create",
196 commandId: CommandId.make(crypto.randomUUID()),199 commandId: CommandId.make(yield* randomUUID),
197 projectId: nextProjectId,200 projectId: nextProjectId,
198 title: bootstrapProjectTitle,201 title: bootstrapProjectTitle,
199 workspaceRoot: serverConfig.cwd,202 workspaceRoot: serverConfig.cwd,
...@@ -210,10 +213,10 @@ export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {...@@ -210,10 +213,10 @@ export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {
210 yield* projectionReadModelQuery.getFirstActiveThreadIdByProjectId(nextProjectId);213 yield* projectionReadModelQuery.getFirstActiveThreadIdByProjectId(nextProjectId);
211 if (Option.isNone(existingThreadId)) {214 if (Option.isNone(existingThreadId)) {
212 const createdAt = DateTime.formatIso(yield* DateTime.now);215 const createdAt = DateTime.formatIso(yield* DateTime.now);
213 const createdThreadId = ThreadId.make(crypto.randomUUID());216 const createdThreadId = ThreadId.make(yield* randomUUID);
214 yield* orchestrationEngine.dispatch({217 yield* orchestrationEngine.dispatch({
215 type: "thread.create",218 type: "thread.create",
216 commandId: CommandId.make(crypto.randomUUID()),219 commandId: CommandId.make(yield* randomUUID),
217 threadId: createdThreadId,220 threadId: createdThreadId,
218 projectId: nextProjectId,221 projectId: nextProjectId,
219 title: "New thread",222 title: "New thread",
apps/server/src/serverSettings.test.ts+13-11
...@@ -16,6 +16,9 @@ import * as Schema from "effect/Schema";...@@ -16,6 +16,9 @@ import * as Schema from "effect/Schema";
16import { ServerConfig } from "./config.ts";16import { ServerConfig } from "./config.ts";
17import { ServerSettingsLive, ServerSettingsService } from "./serverSettings.ts";17import { ServerSettingsLive, ServerSettingsService } from "./serverSettings.ts";
1818
19const decodeSettingsPatch = Schema.decodeUnknownEffect(ServerSettingsPatch);
20const decodeServerSettings = Schema.decodeUnknownEffect(ServerSettings);
21
19const makeServerSettingsLayer = () =>22const makeServerSettingsLayer = () =>
20 ServerSettingsLive.pipe(23 ServerSettingsLive.pipe(
21 Layer.provideMerge(24 Layer.provideMerge(
...@@ -29,15 +32,16 @@ const makeServerSettingsLayer = () =>...@@ -29,15 +32,16 @@ const makeServerSettingsLayer = () =>
2932
30it.layer(NodeServices.layer)("server settings", (it) => {33it.layer(NodeServices.layer)("server settings", (it) => {
31 it.effect("decodes nested settings patches", () =>34 it.effect("decodes nested settings patches", () =>
32 Effect.sync(() => {35 Effect.gen(function* () {
33 const decodePatch = Schema.decodeUnknownSync(ServerSettingsPatch);36 assert.deepEqual(
3437 yield* decodeSettingsPatch({ providers: { codex: { binaryPath: "/tmp/codex" } } }),
35 assert.deepEqual(decodePatch({ providers: { codex: { binaryPath: "/tmp/codex" } } }), {38 {
36 providers: { codex: { binaryPath: "/tmp/codex" } },39 providers: { codex: { binaryPath: "/tmp/codex" } },
37 });40 },
41 );
3842
39 assert.deepEqual(43 assert.deepEqual(
40 decodePatch({44 yield* decodeSettingsPatch({
41 textGenerationModelSelection: {45 textGenerationModelSelection: {
42 options: [{ id: "fastMode", value: false }],46 options: [{ id: "fastMode", value: false }],
43 },47 },
...@@ -54,10 +58,8 @@ it.layer(NodeServices.layer)("server settings", (it) => {...@@ -54,10 +58,8 @@ it.layer(NodeServices.layer)("server settings", (it) => {
54 it.effect(58 it.effect(
55 "decodes legacy object-shaped textGenerationModelSelection.options from settings.json",59 "decodes legacy object-shaped textGenerationModelSelection.options from settings.json",
56 () =>60 () =>
57 Effect.sync(() => {61 Effect.gen(function* () {
58 const decode = Schema.decodeUnknownSync(ServerSettings);62 const decoded = yield* decodeServerSettings({
59
60 const decoded = decode({
61 textGenerationModelSelection: {63 textGenerationModelSelection: {
62 provider: ProviderDriverKind.make("codex"),64 provider: ProviderDriverKind.make("codex"),
63 model: "gpt-5.4-mini",65 model: "gpt-5.4-mini",
apps/server/src/sourceControl/AzureDevOpsCli.ts+1-1
...@@ -94,7 +94,7 @@ export interface AzureDevOpsCliShape {...@@ -94,7 +94,7 @@ export interface AzureDevOpsCliShape {
94}94}
9595
96export class AzureDevOpsCli extends Context.Service<AzureDevOpsCli, AzureDevOpsCliShape>()(96export class AzureDevOpsCli extends Context.Service<AzureDevOpsCli, AzureDevOpsCliShape>()(
97 "t3/source-control/AzureDevOpsCli",97 "t3/sourceControl/AzureDevOpsCli",
98) {}98) {}
9999
100function errorText(error: VcsError | unknown): string {100function errorText(error: VcsError | unknown): string {
apps/server/src/sourceControl/BitbucketApi.ts+1-1
...@@ -154,7 +154,7 @@ export interface BitbucketApiShape {...@@ -154,7 +154,7 @@ export interface BitbucketApiShape {
154}154}
155155
156export class BitbucketApi extends Context.Service<BitbucketApi, BitbucketApiShape>()(156export class BitbucketApi extends Context.Service<BitbucketApi, BitbucketApiShape>()(
157 "t3/source-control/BitbucketApi",157 "t3/sourceControl/BitbucketApi",
158) {}158) {}
159159
160function nonEmpty(value: string | undefined): Option.Option<string> {160function nonEmpty(value: string | undefined): Option.Option<string> {
apps/server/src/sourceControl/GitHubCli.ts+1-1
...@@ -93,7 +93,7 @@ export interface GitHubCliShape {...@@ -93,7 +93,7 @@ export interface GitHubCliShape {
93}93}
9494
95export class GitHubCli extends Context.Service<GitHubCli, GitHubCliShape>()(95export class GitHubCli extends Context.Service<GitHubCli, GitHubCliShape>()(
96 "t3/source-control/GitHubCli",96 "t3/sourceControl/GitHubCli",
97) {}97) {}
9898
99function errorText(error: VcsError | unknown): string {99function errorText(error: VcsError | unknown): string {
apps/server/src/sourceControl/GitLabCli.ts+1-1
...@@ -97,7 +97,7 @@ export interface GitLabCliShape {...@@ -97,7 +97,7 @@ export interface GitLabCliShape {
97}97}
9898
99export class GitLabCli extends Context.Service<GitLabCli, GitLabCliShape>()(99export class GitLabCli extends Context.Service<GitLabCli, GitLabCliShape>()(
100 "t3/source-control/GitLabCli",100 "t3/sourceControl/GitLabCli",
101) {}101) {}
102102
103function isVcsProcessSpawnError(error: unknown): boolean {103function isVcsProcessSpawnError(error: unknown): boolean {
apps/server/src/sourceControl/SourceControlDiscovery.ts+1-1
...@@ -64,7 +64,7 @@ export interface SourceControlDiscoveryShape {...@@ -64,7 +64,7 @@ export interface SourceControlDiscoveryShape {
64export class SourceControlDiscovery extends Context.Service<64export class SourceControlDiscovery extends Context.Service<
65 SourceControlDiscovery,65 SourceControlDiscovery,
66 SourceControlDiscoveryShape66 SourceControlDiscoveryShape
67>()("t3/source-control/SourceControlDiscovery") {}67>()("t3/sourceControl/SourceControlDiscovery") {}
6868
69export const layer = Layer.effect(69export const layer = Layer.effect(
70 SourceControlDiscovery,70 SourceControlDiscovery,
apps/server/src/sourceControl/SourceControlProvider.ts+1-1
...@@ -99,4 +99,4 @@ export interface SourceControlProviderShape {...@@ -99,4 +99,4 @@ export interface SourceControlProviderShape {
99export class SourceControlProvider extends Context.Service<99export class SourceControlProvider extends Context.Service<
100 SourceControlProvider,100 SourceControlProvider,
101 SourceControlProviderShape101 SourceControlProviderShape
102>()("t3/source-control/SourceControlProvider") {}102>()("t3/sourceControl/SourceControlProvider") {}
apps/server/src/sourceControl/SourceControlProviderRegistry.ts+1-1
...@@ -51,7 +51,7 @@ export interface SourceControlProviderRegistryShape {...@@ -51,7 +51,7 @@ export interface SourceControlProviderRegistryShape {
51export class SourceControlProviderRegistry extends Context.Service<51export class SourceControlProviderRegistry extends Context.Service<
52 SourceControlProviderRegistry,52 SourceControlProviderRegistry,
53 SourceControlProviderRegistryShape53 SourceControlProviderRegistryShape
54>()("t3/source-control/SourceControlProviderRegistry") {}54>()("t3/sourceControl/SourceControlProviderRegistry") {}
5555
56function unsupportedProvider(56function unsupportedProvider(
57 kind: SourceControlProviderKind,57 kind: SourceControlProviderKind,
apps/server/src/sourceControl/SourceControlRepositoryService.ts+1-1
...@@ -39,7 +39,7 @@ export interface SourceControlRepositoryServiceShape {...@@ -39,7 +39,7 @@ export interface SourceControlRepositoryServiceShape {
39export class SourceControlRepositoryService extends Context.Service<39export class SourceControlRepositoryService extends Context.Service<
40 SourceControlRepositoryService,40 SourceControlRepositoryService,
41 SourceControlRepositoryServiceShape41 SourceControlRepositoryServiceShape
42>()("t3/source-control/SourceControlRepositoryService") {}42>()("t3/sourceControl/SourceControlRepositoryService") {}
4343
44function detailFromUnknown(cause: unknown): string {44function detailFromUnknown(cause: unknown): string {
45 if (typeof cause === "object" && cause !== null) {45 if (typeof cause === "object" && cause !== null) {
apps/server/src/textGeneration/CodexTextGeneration.ts+16-18
...@@ -76,24 +76,22 @@ export const makeCodexTextGeneration = Effect.fn("makeCodexTextGeneration")(func...@@ -76,24 +76,22 @@ export const makeCodexTextGeneration = Effect.fn("makeCodexTextGeneration")(func
76 operation: string,76 operation: string,
77 prefix: string,77 prefix: string,
78 content: string,78 content: string,
79 ): Effect.Effect<string, TextGenerationError, Scope.Scope> => {79 ): Effect.Effect<string, TextGenerationError, Scope.Scope> =>
80 return Effect.gen(function* () {80 fileSystem
81 return yield* fileSystem81 .makeTempFileScoped({
82 .makeTempFileScoped({82 prefix: `t3code-${prefix}-${process.pid}-`,
83 prefix: `t3code-${prefix}-${process.pid}-`,83 })
84 })84 .pipe(
85 .pipe(Effect.tap((filePath) => fileSystem.writeFileString(filePath, content)));85 Effect.tap((filePath) => fileSystem.writeFileString(filePath, content)),
86 }).pipe(86 Effect.mapError(
87 Effect.mapError(87 (cause) =>
88 (cause) =>88 new TextGenerationError({
89 new TextGenerationError({89 operation,
90 operation,90 detail: `Failed to write temp file`,
91 detail: `Failed to write temp file`,91 cause,
92 cause,92 }),
93 }),93 ),
94 ),94 );
95 );
96 };
9795
98 const safeUnlink = (filePath: string): Effect.Effect<void, never> =>96 const safeUnlink = (filePath: string): Effect.Effect<void, never> =>
99 fileSystem.remove(filePath).pipe(Effect.catch(() => Effect.void));97 fileSystem.remove(filePath).pipe(Effect.catch(() => Effect.void));
apps/server/src/textGeneration/TextGeneration.ts+1-1
...@@ -116,7 +116,7 @@ export interface TextGenerationShape {...@@ -116,7 +116,7 @@ export interface TextGenerationShape {
116 * TextGeneration - Service tag for commit and PR text generation.116 * TextGeneration - Service tag for commit and PR text generation.
117 */117 */
118export class TextGeneration extends Context.Service<TextGeneration, TextGenerationShape>()(118export class TextGeneration extends Context.Service<TextGeneration, TextGenerationShape>()(
119 "t3/text-generation/TextGeneration",119 "t3/textGeneration/TextGeneration",
120) {}120) {}
121121
122type TextGenerationOp =122type TextGenerationOp =
apps/server/src/ws.ts+49-32
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1import * as Cause from "effect/Cause";1import * as Cause from "effect/Cause";
2import * as Crypto from "effect/Crypto";
2import * as DateTime from "effect/DateTime";3import * as DateTime from "effect/DateTime";
3import * as Duration from "effect/Duration";4import * as Duration from "effect/Duration";
4import * as Effect from "effect/Effect";5import * as Effect from "effect/Effect";
...@@ -160,6 +161,7 @@ function toAuthAccessStreamEvent(...@@ -160,6 +161,7 @@ function toAuthAccessStreamEvent(
160const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>161const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
161 WsRpcGroup.toLayer(162 WsRpcGroup.toLayer(
162 Effect.gen(function* () {163 Effect.gen(function* () {
164 const crypto = yield* Crypto.Crypto;
163 const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;165 const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
164 const orchestrationEngine = yield* OrchestrationEngineService;166 const orchestrationEngine = yield* OrchestrationEngineService;
165 const checkpointDiffQuery = yield* CheckpointDiffQuery;167 const checkpointDiffQuery = yield* CheckpointDiffQuery;
...@@ -195,8 +197,21 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>...@@ -195,8 +197,21 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
195 const sessions = yield* SessionCredentialService;197 const sessions = yield* SessionCredentialService;
196 const processDiagnostics = yield* ProcessDiagnostics.ProcessDiagnostics;198 const processDiagnostics = yield* ProcessDiagnostics.ProcessDiagnostics;
197 const processResourceMonitor = yield* ProcessResourceMonitor.ProcessResourceMonitor;199 const processResourceMonitor = yield* ProcessResourceMonitor.ProcessResourceMonitor;
200 const toDispatchCommandError = (cause: unknown, fallbackMessage: string) =>
201 isOrchestrationDispatchCommandError(cause)
202 ? cause
203 : new OrchestrationDispatchCommandError({
204 message: cause instanceof Error ? cause.message : fallbackMessage,
205 cause,
206 });
207 const randomUUID = crypto.randomUUIDv4.pipe(
208 Effect.mapError((cause) =>
209 toDispatchCommandError(cause, "Failed to generate orchestration command identifier."),
210 ),
211 );
212 const serverEventId = randomUUID.pipe(Effect.map(EventId.make));
198 const serverCommandId = (tag: string) =>213 const serverCommandId = (tag: string) =>
199 CommandId.make(`server:${tag}:${crypto.randomUUID()}`);214 randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`)));
200215
201 const loadAuthAccessSnapshot = () =>216 const loadAuthAccessSnapshot = () =>
202 Effect.all({217 Effect.all({
...@@ -212,29 +227,28 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>...@@ -212,29 +227,28 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
212 readonly payload: Record<string, unknown>;227 readonly payload: Record<string, unknown>;
213 readonly tone: "info" | "error";228 readonly tone: "info" | "error";
214 }) =>229 }) =>
215 orchestrationEngine.dispatch({230 Effect.all({
216 type: "thread.activity.append",
217 commandId: serverCommandId("setup-script-activity"),231 commandId: serverCommandId("setup-script-activity"),
218 threadId: input.threadId,232 activityId: serverEventId,
219 activity: {233 }).pipe(
220 id: EventId.make(crypto.randomUUID()),234 Effect.flatMap(({ commandId, activityId }) =>
221 tone: input.tone,235 orchestrationEngine.dispatch({
222 kind: input.kind,236 type: "thread.activity.append",
223 summary: input.summary,237 commandId,
224 payload: input.payload,238 threadId: input.threadId,
225 turnId: null,239 activity: {
226 createdAt: input.createdAt,240 id: activityId,
227 },241 tone: input.tone,
228 createdAt: input.createdAt,242 kind: input.kind,
229 });243 summary: input.summary,
230244 payload: input.payload,
231 const toDispatchCommandError = (cause: unknown, fallbackMessage: string) =>245 turnId: null,
232 isOrchestrationDispatchCommandError(cause)246 createdAt: input.createdAt,
233 ? cause247 },
234 : new OrchestrationDispatchCommandError({248 createdAt: input.createdAt,
235 message: cause instanceof Error ? cause.message : fallbackMessage,249 }),
236 cause,250 ),
237 });251 );
238252
239 const toBootstrapDispatchCommandCauseError = (cause: Cause.Cause<unknown>) => {253 const toBootstrapDispatchCommandCauseError = (cause: Cause.Cause<unknown>) => {
240 const error = Cause.squash(cause);254 const error = Cause.squash(cause);
...@@ -370,13 +384,16 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>...@@ -370,13 +384,16 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
370384
371 const cleanupCreatedThread = () =>385 const cleanupCreatedThread = () =>
372 createdThread386 createdThread
373 ? orchestrationEngine387 ? serverCommandId("bootstrap-thread-delete").pipe(
374 .dispatch({388 Effect.flatMap((commandId) =>
375 type: "thread.delete",389 orchestrationEngine.dispatch({
376 commandId: serverCommandId("bootstrap-thread-delete"),390 type: "thread.delete",
377 threadId: command.threadId,391 commandId,
378 })392 threadId: command.threadId,
379 .pipe(Effect.ignoreCause({ log: true }))393 }),
394 ),
395 Effect.ignoreCause({ log: true }),
396 )
380 : Effect.void;397 : Effect.void;
381398
382 const recordSetupScriptLaunchFailure = (input: {399 const recordSetupScriptLaunchFailure = (input: {
...@@ -499,7 +516,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>...@@ -499,7 +516,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
499 if (bootstrap?.createThread) {516 if (bootstrap?.createThread) {
500 yield* orchestrationEngine.dispatch({517 yield* orchestrationEngine.dispatch({
501 type: "thread.create",518 type: "thread.create",
502 commandId: serverCommandId("bootstrap-thread-create"),519 commandId: yield* serverCommandId("bootstrap-thread-create"),
503 threadId: command.threadId,520 threadId: command.threadId,
504 projectId: bootstrap.createThread.projectId,521 projectId: bootstrap.createThread.projectId,
505 title: bootstrap.createThread.title,522 title: bootstrap.createThread.title,
...@@ -523,7 +540,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>...@@ -523,7 +540,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
523 targetWorktreePath = worktree.worktree.path;540 targetWorktreePath = worktree.worktree.path;
524 yield* orchestrationEngine.dispatch({541 yield* orchestrationEngine.dispatch({
525 type: "thread.meta.update",542 type: "thread.meta.update",
526 commandId: serverCommandId("bootstrap-thread-meta-update"),543 commandId: yield* serverCommandId("bootstrap-thread-meta-update"),
527 threadId: command.threadId,544 threadId: command.threadId,
528 branch: worktree.worktree.refName,545 branch: worktree.worktree.refName,
529 worktreePath: targetWorktreePath,546 worktreePath: targetWorktreePath,
apps/server/tsconfig.json-1
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1{1{
2 "extends": "../../tsconfig.base.json",2 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {3 "compilerOptions": {
4 "composite": true,
5 "types": ["node", "bun"],4 "types": ["node", "bun"],
6 "lib": ["ESNext", "esnext.disposable"]5 "lib": ["ESNext", "esnext.disposable"]
7 },6 },
apps/web/package.json+1-3
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7 "dev": "vite",7 "dev": "vite",
8 "build": "vite build",8 "build": "vite build",
9 "preview": "vite preview",9 "preview": "vite preview",
10 "typecheck": "tsc --noEmit",10 "typecheck": "tsgo --noEmit",
11 "test": "vitest run --passWithNoTests",11 "test": "vitest run --passWithNoTests",
12 "test:browser": "vitest run --config vitest.browser.config.ts",12 "test:browser": "vitest run --config vitest.browser.config.ts",
13 "test:browser:install": "playwright install --with-deps chromium"13 "test:browser:install": "playwright install --with-deps chromium"
...@@ -43,7 +43,6 @@...@@ -43,7 +43,6 @@
43 "zustand": "^5.0.11"43 "zustand": "^5.0.11"
44 },44 },
45 "devDependencies": {45 "devDependencies": {
46 "@effect/language-service": "catalog:",
47 "@rolldown/plugin-babel": "^0.2.0",46 "@rolldown/plugin-babel": "^0.2.0",
48 "@tailwindcss/vite": "^4.0.0",47 "@tailwindcss/vite": "^4.0.0",
49 "@tanstack/router-plugin": "^1.161.0",48 "@tanstack/router-plugin": "^1.161.0",
...@@ -57,7 +56,6 @@...@@ -57,7 +56,6 @@
57 "msw": "2.12.11",56 "msw": "2.12.11",
58 "playwright": "^1.58.2",57 "playwright": "^1.58.2",
59 "tailwindcss": "^4.0.0",58 "tailwindcss": "^4.0.0",
60 "typescript": "catalog:",
61 "vite": "^8.0.0",59 "vite": "^8.0.0",
62 "vitest": "catalog:",60 "vitest": "catalog:",
63 "vitest-browser-react": "^2.0.5"61 "vitest-browser-react": "^2.0.5"
apps/web/src/session-logic.test.ts+3-1
...@@ -22,6 +22,8 @@ import {...@@ -22,6 +22,8 @@ import {
22 isLatestTurnSettled,22 isLatestTurnSettled,
23} from "./session-logic";23} from "./session-logic";
2424
25let nextActivityId = 0;
26
25function makeActivity(overrides: {27function makeActivity(overrides: {
26 id?: string;28 id?: string;
27 createdAt?: string;29 createdAt?: string;
...@@ -34,7 +36,7 @@ function makeActivity(overrides: {...@@ -34,7 +36,7 @@ function makeActivity(overrides: {
34}): OrchestrationThreadActivity {36}): OrchestrationThreadActivity {
35 const payload = overrides.payload ?? {};37 const payload = overrides.payload ?? {};
36 return {38 return {
37 id: EventId.make(overrides.id ?? crypto.randomUUID()),39 id: EventId.make(overrides.id ?? `activity-${nextActivityId++}`),
38 createdAt: overrides.createdAt ?? "2026-02-23T00:00:00.000Z",40 createdAt: overrides.createdAt ?? "2026-02-23T00:00:00.000Z",
39 kind: overrides.kind ?? "tool.started",41 kind: overrides.kind ?? "tool.started",
40 summary: overrides.summary ?? "Tool call",42 summary: overrides.summary ?? "Tool call",
apps/web/tsconfig.json+6-15
...@@ -15,22 +15,13 @@...@@ -15,22 +15,13 @@
15 "plugins": [15 "plugins": [
16 {16 {
17 "name": "@effect/language-service",17 "name": "@effect/language-service",
18 "namespaceImportPackages": ["@effect/platform-node", "effect"],18 // Diagnostic severities are deep-merged with tsconfig.base.json; list only web-specific overrides here.
19 "diagnosticSeverity": {19 "diagnosticSeverity": {
20 "importFromBarrel": "error",20 "globalDate": "off",
21 "anyUnknownInErrorContext": "error",21 "globalConsole": "off",
22 "unsafeEffectTypeAssertion": "error",22 "globalRandom": "off",
23 "instanceOfSchema": "error",23 "globalTimers": "off",
24 "deterministicKeys": "error",24 "globalFetch": "off"
25 "strictEffectProvide": "off",
26 "missingEffectServiceDependency": "error",
27 "leakingRequirements": "error",
28 "globalErrorInEffectCatch": "error",
29 "globalErrorInEffectFailure": "error",
30 "unknownInEffectCatch": "error",
31 "strictBooleanExpressions": "off",
32 "preferSchemaOverJson": "error",
33 "schemaSyncInEffect": "error"
34 }25 }
35 }26 }
36 ]27 ]
bun.lock+40-31
...@@ -5,13 +5,13 @@...@@ -5,13 +5,13 @@
5 "": {5 "": {
6 "name": "@t3tools/monorepo",6 "name": "@t3tools/monorepo",
7 "devDependencies": {7 "devDependencies": {
8 "@effect/language-service": "catalog:",8 "@effect/tsgo": "catalog:",
9 "@oxlint/plugins": "^1.63.0",9 "@oxlint/plugins": "^1.63.0",
10 "@types/node": "catalog:",10 "@types/node": "catalog:",
11 "@typescript/native-preview": "catalog:",
11 "oxfmt": "^0.40.0",12 "oxfmt": "^0.40.0",
12 "oxlint": "^1.63.0",13 "oxlint": "^1.63.0",
13 "turbo": "^2.3.3",14 "turbo": "^2.3.3",
14 "typescript": "catalog:",
15 "vitest": "catalog:",15 "vitest": "catalog:",
16 },16 },
17 },17 },
...@@ -29,11 +29,9 @@...@@ -29,11 +29,9 @@
29 "electron-updater": "^6.6.2",29 "electron-updater": "^6.6.2",
30 },30 },
31 "devDependencies": {31 "devDependencies": {
32 "@effect/language-service": "catalog:",
33 "@effect/vitest": "catalog:",32 "@effect/vitest": "catalog:",
34 "@types/node": "catalog:",33 "@types/node": "catalog:",
35 "tsdown": "catalog:",34 "tsdown": "catalog:",
36 "typescript": "catalog:",
37 "vitest": "catalog:",35 "vitest": "catalog:",
38 },36 },
39 },37 },
...@@ -66,7 +64,6 @@...@@ -66,7 +64,6 @@
66 "node-pty": "^1.1.0",64 "node-pty": "^1.1.0",
67 },65 },
68 "devDependencies": {66 "devDependencies": {
69 "@effect/language-service": "catalog:",
70 "@effect/vitest": "catalog:",67 "@effect/vitest": "catalog:",
71 "@t3tools/contracts": "workspace:*",68 "@t3tools/contracts": "workspace:*",
72 "@t3tools/shared": "workspace:*",69 "@t3tools/shared": "workspace:*",
...@@ -77,7 +74,6 @@...@@ -77,7 +74,6 @@
77 "effect-acp": "workspace:*",74 "effect-acp": "workspace:*",
78 "effect-codex-app-server": "workspace:*",75 "effect-codex-app-server": "workspace:*",
79 "tsdown": "catalog:",76 "tsdown": "catalog:",
80 "typescript": "catalog:",
81 "vitest": "catalog:",77 "vitest": "catalog:",
82 },78 },
83 },79 },
...@@ -115,7 +111,6 @@...@@ -115,7 +111,6 @@
115 "zustand": "^5.0.11",111 "zustand": "^5.0.11",
116 },112 },
117 "devDependencies": {113 "devDependencies": {
118 "@effect/language-service": "catalog:",
119 "@rolldown/plugin-babel": "^0.2.0",114 "@rolldown/plugin-babel": "^0.2.0",
120 "@tailwindcss/vite": "^4.0.0",115 "@tailwindcss/vite": "^4.0.0",
121 "@tanstack/router-plugin": "^1.161.0",116 "@tanstack/router-plugin": "^1.161.0",
...@@ -129,7 +124,6 @@...@@ -129,7 +124,6 @@
129 "msw": "2.12.11",124 "msw": "2.12.11",
130 "playwright": "^1.58.2",125 "playwright": "^1.58.2",
131 "tailwindcss": "^4.0.0",126 "tailwindcss": "^4.0.0",
132 "typescript": "catalog:",
133 "vite": "^8.0.0",127 "vite": "^8.0.0",
134 "vitest": "catalog:",128 "vitest": "catalog:",
135 "vitest-browser-react": "^2.0.5",129 "vitest-browser-react": "^2.0.5",
...@@ -143,10 +137,8 @@...@@ -143,10 +137,8 @@
143 "effect": "catalog:",137 "effect": "catalog:",
144 },138 },
145 "devDependencies": {139 "devDependencies": {
146 "@effect/language-service": "catalog:",
147 "@effect/vitest": "catalog:",140 "@effect/vitest": "catalog:",
148 "@types/bun": "catalog:",141 "@types/bun": "catalog:",
149 "typescript": "catalog:",
150 "vitest": "catalog:",142 "vitest": "catalog:",
151 },143 },
152 },144 },
...@@ -158,8 +150,6 @@...@@ -158,8 +150,6 @@
158 "effect": "catalog:",150 "effect": "catalog:",
159 },151 },
160 "devDependencies": {152 "devDependencies": {
161 "@effect/language-service": "catalog:",
162 "typescript": "catalog:",
163 "vitest": "catalog:",153 "vitest": "catalog:",
164 },154 },
165 },155 },
...@@ -170,9 +160,7 @@...@@ -170,9 +160,7 @@
170 "effect": "catalog:",160 "effect": "catalog:",
171 },161 },
172 "devDependencies": {162 "devDependencies": {
173 "@effect/language-service": "catalog:",
174 "@effect/vitest": "catalog:",163 "@effect/vitest": "catalog:",
175 "typescript": "catalog:",
176 "vitest": "catalog:",164 "vitest": "catalog:",
177 },165 },
178 },166 },
...@@ -182,11 +170,10 @@...@@ -182,11 +170,10 @@
182 "effect": "catalog:",170 "effect": "catalog:",
183 },171 },
184 "devDependencies": {172 "devDependencies": {
185 "@effect/language-service": "catalog:",
186 "@effect/openapi-generator": "catalog:",173 "@effect/openapi-generator": "catalog:",
187 "@effect/platform-node": "catalog:",174 "@effect/platform-node": "catalog:",
188 "@effect/vitest": "catalog:",175 "@effect/vitest": "catalog:",
189 "typescript": "catalog:",176 "@types/node": "catalog:",
190 "vitest": "catalog:",177 "vitest": "catalog:",
191 },178 },
192 },179 },
...@@ -196,11 +183,10 @@...@@ -196,11 +183,10 @@
196 "effect": "catalog:",183 "effect": "catalog:",
197 },184 },
198 "devDependencies": {185 "devDependencies": {
199 "@effect/language-service": "catalog:",
200 "@effect/openapi-generator": "catalog:",186 "@effect/openapi-generator": "catalog:",
201 "@effect/platform-node": "catalog:",187 "@effect/platform-node": "catalog:",
202 "@effect/vitest": "catalog:",188 "@effect/vitest": "catalog:",
203 "typescript": "catalog:",189 "@types/node": "catalog:",
204 "vitest": "catalog:",190 "vitest": "catalog:",
205 },191 },
206 },192 },
...@@ -211,11 +197,9 @@...@@ -211,11 +197,9 @@
211 "effect": "catalog:",197 "effect": "catalog:",
212 },198 },
213 "devDependencies": {199 "devDependencies": {
214 "@effect/language-service": "catalog:",
215 "@effect/platform-node": "catalog:",200 "@effect/platform-node": "catalog:",
216 "@effect/vitest": "catalog:",201 "@effect/vitest": "catalog:",
217 "@types/node": "catalog:",202 "@types/node": "catalog:",
218 "typescript": "catalog:",
219 "vitest": "catalog:",203 "vitest": "catalog:",
220 },204 },
221 },205 },
...@@ -227,11 +211,9 @@...@@ -227,11 +211,9 @@
227 "effect": "catalog:",211 "effect": "catalog:",
228 },212 },
229 "devDependencies": {213 "devDependencies": {
230 "@effect/language-service": "catalog:",
231 "@effect/platform-node": "catalog:",214 "@effect/platform-node": "catalog:",
232 "@effect/vitest": "catalog:",215 "@effect/vitest": "catalog:",
233 "@types/node": "catalog:",216 "@types/node": "catalog:",
234 "typescript": "catalog:",
235 "vitest": "catalog:",217 "vitest": "catalog:",
236 },218 },
237 },219 },
...@@ -242,10 +224,8 @@...@@ -242,10 +224,8 @@
242 "effect": "catalog:",224 "effect": "catalog:",
243 },225 },
244 "devDependencies": {226 "devDependencies": {
245 "@effect/language-service": "catalog:",
246 "@effect/vitest": "catalog:",227 "@effect/vitest": "catalog:",
247 "@types/node": "catalog:",228 "@types/node": "catalog:",
248 "typescript": "catalog:",
249 "vitest": "catalog:",229 "vitest": "catalog:",
250 },230 },
251 },231 },
...@@ -259,10 +239,8 @@...@@ -259,10 +239,8 @@
259 "effect": "catalog:",239 "effect": "catalog:",
260 },240 },
261 "devDependencies": {241 "devDependencies": {
262 "@effect/language-service": "catalog:",
263 "@effect/vitest": "catalog:",242 "@effect/vitest": "catalog:",
264 "@types/bun": "catalog:",243 "@types/bun": "catalog:",
265 "typescript": "catalog:",
266 "vitest": "catalog:",244 "vitest": "catalog:",
267 },245 },
268 },246 },
...@@ -286,19 +264,20 @@...@@ -286,19 +264,20 @@
286 },264 },
287 "catalog": {265 "catalog": {
288 "@effect/atom-react": "4.0.0-beta.73",266 "@effect/atom-react": "4.0.0-beta.73",
289 "@effect/language-service": "0.84.2",
290 "@effect/openapi-generator": "4.0.0-beta.73",267 "@effect/openapi-generator": "4.0.0-beta.73",
291 "@effect/platform-bun": "4.0.0-beta.73",268 "@effect/platform-bun": "4.0.0-beta.73",
292 "@effect/platform-node": "4.0.0-beta.73",269 "@effect/platform-node": "4.0.0-beta.73",
293 "@effect/platform-node-shared": "4.0.0-beta.73",270 "@effect/platform-node-shared": "4.0.0-beta.73",
294 "@effect/sql-sqlite-bun": "4.0.0-beta.73",271 "@effect/sql-sqlite-bun": "4.0.0-beta.73",
272 "@effect/tsgo": "0.11.4",
295 "@effect/vitest": "4.0.0-beta.73",273 "@effect/vitest": "4.0.0-beta.73",
296 "@pierre/diffs": "1.1.20",274 "@pierre/diffs": "1.1.20",
297 "@types/bun": "^1.3.11",275 "@types/bun": "^1.3.11",
298 "@types/node": "^24.10.13",276 "@types/node": "^24.10.13",
277 "@typescript/native-preview": "7.0.0-dev.20260527.2",
299 "effect": "4.0.0-beta.73",278 "effect": "4.0.0-beta.73",
300 "tsdown": "^0.20.3",279 "tsdown": "^0.20.3",
301 "typescript": "^5.7.3",280 "typescript": "~6.0.3",
302 "vitest": "^4.0.0",281 "vitest": "^4.0.0",
303 },282 },
304 "packages": {283 "packages": {
...@@ -402,8 +381,6 @@...@@ -402,8 +381,6 @@
402381
403 "@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=="],382 "@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=="],
404383
405 "@effect/language-service": ["@effect/language-service@0.84.2", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-l04qNxpiA8rY5yXWckRPJ7Mk5MNerXuNymSFf+IdflfI5i8jgL1bpBNLuP6ijg7wgjdHc/KmTnCj2kT0SCntuA=="],
406
407 "@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=="],384 "@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=="],
408385
409 "@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=="],386 "@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=="],
...@@ -414,6 +391,22 @@...@@ -414,6 +391,22 @@
414391
415 "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.73", "", { "peerDependencies": { "effect": "^4.0.0-beta.73" } }, "sha512-dkTDDeBLjaKo7h1IE049Oj2BDKQOT+Kc57KbBVaSk36dRdsEmVspRMP7OGbZj3etJU3lL1GJi1BIfnb4N3uMRw=="],392 "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.73", "", { "peerDependencies": { "effect": "^4.0.0-beta.73" } }, "sha512-dkTDDeBLjaKo7h1IE049Oj2BDKQOT+Kc57KbBVaSk36dRdsEmVspRMP7OGbZj3etJU3lL1GJi1BIfnb4N3uMRw=="],
416393
394 "@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=="],
395
396 "@effect/tsgo-darwin-arm64": ["@effect/tsgo-darwin-arm64@0.11.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rslT4W8tWY8pdd48kDpY7Q+yo0xkrmcEySG1+sJfb06w7TwbywjHsGlC0BmcUaQt0qmLY+BApbWWDfZw7fgwjw=="],
397
398 "@effect/tsgo-darwin-x64": ["@effect/tsgo-darwin-x64@0.11.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-p3v3j+zp7L7yx5ctjvA1W85I4WjOpbOcga8kUu5MFEKfYfsApxUHXwsunCVbUKwrpXqcTc0sw9AjnCNs6i6GRw=="],
399
400 "@effect/tsgo-linux-arm": ["@effect/tsgo-linux-arm@0.11.4", "", { "os": "linux", "cpu": "arm" }, "sha512-uXsw+IbO+ltn/fbhOWWqXK8ZW3Qa5EZD+wnGbF3gIGWINthbF+/7X+CgRzvcgLBWeBfV6F83hAmOaEZ4hQmd+w=="],
401
402 "@effect/tsgo-linux-arm64": ["@effect/tsgo-linux-arm64@0.11.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-dz5ZIQUnRzN9mpVcELYCmVERpmstes5rVHbKUb7DOWCbrbupT3tV1LCzOaNX9sIsoBKmpvdGvAWEPLHgymSgTQ=="],
403
404 "@effect/tsgo-linux-x64": ["@effect/tsgo-linux-x64@0.11.4", "", { "os": "linux", "cpu": "x64" }, "sha512-P3m7Y4FJtziL13Muffyb99AnQeTRvo0/knfYRqoHKNwYUaNM59RO3qFi5y57Hasgd8rKat0xTPmUkK6koZPPFQ=="],
405
406 "@effect/tsgo-win32-arm64": ["@effect/tsgo-win32-arm64@0.11.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-FKLm9Y+luZSdLpfkbdw8VXa8xy0zR+Asg078qemqHHGwRQLDVGjvIk7tj1HxBM6VQN+TwsofDd225ht83kMk8w=="],
407
408 "@effect/tsgo-win32-x64": ["@effect/tsgo-win32-x64@0.11.4", "", { "os": "win32", "cpu": "x64" }, "sha512-oc4Y8TbLlv0b1deAILAEep1N6pnSS1d4pk7gJJM4NDXrTKWDyEulO6tXwRQ6vWkO2lhLTUVWHDFfzmMJj3HxPQ=="],
409
417 "@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=="],410 "@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=="],
418411
419 "@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=="],412 "@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=="],
...@@ -934,6 +927,22 @@...@@ -934,6 +927,22 @@
934927
935 "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],928 "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],
936929
930 "@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=="],
931
932 "@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=="],
933
934 "@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=="],
935
936 "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260527.2", "", { "os": "linux", "cpu": "arm" }, "sha512-6I9Cv9ozwfS9zB9vRQDPIYseLX3artEO9jl3yVgLj4ishwlSF4cWAbIsjl5IztPaEgHv8coej/6tX1D0uaBzXg=="],
937
938 "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260527.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-BGUDMjC2Z3TTdZRkGGwhBLelkP5UYgO2rbep8aF4dS3fu7T5lFPPrnfS6EgqJgie+cF5Fsev7xEq8wWyBDM+lg=="],
939
940 "@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=="],
941
942 "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260527.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-DBFnFE3V6AITkPO1K1VxXf3yEZKjU2FwtXlNwRqhzDu0rrL2SsJHOSrBDX+OacTxQFzZMxFcpiuhV8jHZALPEg=="],
943
944 "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260527.2", "", { "os": "win32", "cpu": "x64" }, "sha512-1tBlErMvQgcMqqYwsx4tytupcjCJcOUXD3vBn1Wb/kAvus1FzWQAFE0fcKBvLfcqLQfTiiEwKKEtbLjGmakqqg=="],
945
937 "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],946 "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
938947
939 "@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=="],948 "@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=="],
...@@ -1982,7 +1991,7 @@...@@ -1982,7 +1991,7 @@
19821991
1983 "typesafe-path": ["typesafe-path@0.2.2", "", {}, "sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA=="],1992 "typesafe-path": ["typesafe-path@0.2.2", "", {}, "sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA=="],
19841993
1985 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],1994 "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
19861995
1987 "typescript-auto-import-cache": ["typescript-auto-import-cache@0.3.6", "", { "dependencies": { "semver": "^7.3.8" } }, "sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ=="],1996 "typescript-auto-import-cache": ["typescript-auto-import-cache@0.3.6", "", { "dependencies": { "semver": "^7.3.8" } }, "sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ=="],
19881997
oxlint-plugin-t3code/package.json+1-3
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3 "private": true,3 "private": true,
4 "type": "module",4 "type": "module",
5 "scripts": {5 "scripts": {
6 "typecheck": "tsc --noEmit",6 "typecheck": "tsgo --noEmit",
7 "test": "vitest run"7 "test": "vitest run"
8 },8 },
9 "dependencies": {9 "dependencies": {
...@@ -12,10 +12,8 @@...@@ -12,10 +12,8 @@
12 "effect": "catalog:"12 "effect": "catalog:"
13 },13 },
14 "devDependencies": {14 "devDependencies": {
15 "@effect/language-service": "catalog:",
16 "@effect/vitest": "catalog:",15 "@effect/vitest": "catalog:",
17 "@types/bun": "catalog:",16 "@types/bun": "catalog:",
18 "typescript": "catalog:",
19 "vitest": "catalog:"17 "vitest": "catalog:"
20 }18 }
21}19}
package.json+6-5
...@@ -17,18 +17,19 @@...@@ -17,18 +17,19 @@
17 "@effect/platform-node-shared": "4.0.0-beta.73",17 "@effect/platform-node-shared": "4.0.0-beta.73",
18 "@effect/sql-sqlite-bun": "4.0.0-beta.73",18 "@effect/sql-sqlite-bun": "4.0.0-beta.73",
19 "@effect/vitest": "4.0.0-beta.73",19 "@effect/vitest": "4.0.0-beta.73",
20 "@effect/language-service": "0.84.2",20 "@effect/tsgo": "0.11.4",
21 "@pierre/diffs": "1.1.20",21 "@pierre/diffs": "1.1.20",
22 "@types/bun": "^1.3.11",22 "@types/bun": "^1.3.11",
23 "@types/node": "^24.10.13",23 "@types/node": "^24.10.13",
24 "@typescript/native-preview": "7.0.0-dev.20260527.2",
24 "tsdown": "^0.20.3",25 "tsdown": "^0.20.3",
25 "typescript": "^5.7.3",26 "typescript": "~6.0.3",
26 "vitest": "^4.0.0"27 "vitest": "^4.0.0"
27 }28 }
28 },29 },
29 "type": "module",30 "type": "module",
30 "scripts": {31 "scripts": {
31 "prepare": "effect-language-service patch",32 "prepare": "effect-tsgo patch",
32 "dev": "node scripts/dev-runner.ts dev",33 "dev": "node scripts/dev-runner.ts dev",
33 "dev:server": "node scripts/dev-runner.ts dev:server",34 "dev:server": "node scripts/dev-runner.ts dev:server",
34 "dev:web": "node scripts/dev-runner.ts dev:web",35 "dev:web": "node scripts/dev-runner.ts dev:web",
...@@ -61,13 +62,13 @@...@@ -61,13 +62,13 @@
61 "sync:vscode-icons": "node scripts/sync-vscode-icons.mjs"62 "sync:vscode-icons": "node scripts/sync-vscode-icons.mjs"
62 },63 },
63 "devDependencies": {64 "devDependencies": {
64 "@effect/language-service": "catalog:",65 "@effect/tsgo": "catalog:",
65 "@oxlint/plugins": "^1.63.0",66 "@oxlint/plugins": "^1.63.0",
66 "@types/node": "catalog:",67 "@types/node": "catalog:",
68 "@typescript/native-preview": "catalog:",
67 "oxfmt": "^0.40.0",69 "oxfmt": "^0.40.0",
68 "oxlint": "^1.63.0",70 "oxlint": "^1.63.0",
69 "turbo": "^2.3.3",71 "turbo": "^2.3.3",
70 "typescript": "catalog:",
71 "vitest": "catalog:"72 "vitest": "catalog:"
72 },73 },
73 "overrides": {74 "overrides": {
packages/client-runtime/package.json+1-3
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9 }9 }
10 },10 },
11 "scripts": {11 "scripts": {
12 "typecheck": "tsc --noEmit",12 "typecheck": "tsgo --noEmit",
13 "test": "vitest run"13 "test": "vitest run"
14 },14 },
15 "dependencies": {15 "dependencies": {
...@@ -18,8 +18,6 @@...@@ -18,8 +18,6 @@
18 "effect": "catalog:"18 "effect": "catalog:"
19 },19 },
20 "devDependencies": {20 "devDependencies": {
21 "@effect/language-service": "catalog:",
22 "typescript": "catalog:",
23 "vitest": "catalog:"21 "vitest": "catalog:"
24 }22 }
25}23}
packages/contracts/package.json+1-3
...@@ -17,16 +17,14 @@...@@ -17,16 +17,14 @@
17 }17 }
18 },18 },
19 "scripts": {19 "scripts": {
20 "typecheck": "tsc --noEmit",20 "typecheck": "tsgo --noEmit",
21 "test": "vitest run"21 "test": "vitest run"
22 },22 },
23 "dependencies": {23 "dependencies": {
24 "effect": "catalog:"24 "effect": "catalog:"
25 },25 },
26 "devDependencies": {26 "devDependencies": {
27 "@effect/language-service": "catalog:",
28 "@effect/vitest": "catalog:",27 "@effect/vitest": "catalog:",
29 "typescript": "catalog:",
30 "vitest": "catalog:"28 "vitest": "catalog:"
31 }29 }
32}30}
packages/contracts/src/orchestration.test.ts+4-3
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1import assert from "node:assert/strict";1import { assert, it } from "@effect/vitest";
2import { it } from "@effect/vitest";
3import * as Effect from "effect/Effect";2import * as Effect from "effect/Effect";
4import * as Schema from "effect/Schema";3import * as Schema from "effect/Schema";
54
...@@ -379,7 +378,9 @@ it.effect("decodes thread archived and unarchived events", () =>...@@ -379,7 +378,9 @@ it.effect("decodes thread archived and unarchived events", () =>
379 },378 },
380 });379 });
381380
382 assert.strictEqual(archived.type, "thread.archived");381 if (archived.type !== "thread.archived") {
382 assert.fail(`Expected thread.archived event, received ${archived.type}.`);
383 }
383 assert.strictEqual(archived.payload.archivedAt, "2026-01-01T00:00:00.000Z");384 assert.strictEqual(archived.payload.archivedAt, "2026-01-01T00:00:00.000Z");
384 assert.strictEqual(unarchived.type, "thread.unarchived");385 assert.strictEqual(unarchived.type, "thread.unarchived");
385 }),386 }),
packages/effect-acp/package.json+2-3
...@@ -33,7 +33,7 @@...@@ -33,7 +33,7 @@
33 }33 }
34 },34 },
35 "scripts": {35 "scripts": {
36 "typecheck": "tsc --noEmit",36 "typecheck": "tsgo --noEmit",
37 "test": "vitest run",37 "test": "vitest run",
38 "generate": "bun run scripts/generate.ts"38 "generate": "bun run scripts/generate.ts"
39 },39 },
...@@ -41,11 +41,10 @@...@@ -41,11 +41,10 @@
41 "effect": "catalog:"41 "effect": "catalog:"
42 },42 },
43 "devDependencies": {43 "devDependencies": {
44 "@effect/language-service": "catalog:",
45 "@effect/openapi-generator": "catalog:",44 "@effect/openapi-generator": "catalog:",
46 "@effect/platform-node": "catalog:",45 "@effect/platform-node": "catalog:",
47 "@effect/vitest": "catalog:",46 "@effect/vitest": "catalog:",
48 "typescript": "catalog:",47 "@types/node": "catalog:",
49 "vitest": "catalog:"48 "vitest": "catalog:"
50 }49 }
51}50}
packages/effect-acp/scripts/generate.ts+3-6
...@@ -146,7 +146,7 @@ function collectSchemaEntries(...@@ -146,7 +146,7 @@ function collectSchemaEntries(
146 return entries;146 return entries;
147}147}
148148
149function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.Json.Type {149function normalizeNullableTypes(value: Schema.Json): Schema.Json {
150 if (Array.isArray(value)) {150 if (Array.isArray(value)) {
151 return value.map(normalizeNullableTypes);151 return value.map(normalizeNullableTypes);
152 }152 }
...@@ -158,10 +158,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J...@@ -158,10 +158,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
158 key,158 key,
159 normalizeNullableTypes(child),159 normalizeNullableTypes(child),
160 ]);160 ]);
161 const normalizedObject = Object.fromEntries(normalizedEntries) as Record<161 const normalizedObject = Object.fromEntries(normalizedEntries) as Record<string, Schema.Json>;
162 string,
163 typeof Schema.Json.Type
164 >;
165 const typeValue = normalizedObject.type;162 const typeValue = normalizedObject.type;
166163
167 if (!Array.isArray(typeValue)) {164 if (!Array.isArray(typeValue)) {
...@@ -179,7 +176,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J...@@ -179,7 +176,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
179 }176 }
180 const nonNullType = nonNullTypes[0]!;177 const nonNullType = nonNullTypes[0]!;
181178
182 const nextObject: Record<string, typeof Schema.Json.Type> = {};179 const nextObject: Record<string, Schema.Json> = {};
183 for (const [key, child] of Object.entries(normalizedObject)) {180 for (const [key, child] of Object.entries(normalizedObject)) {
184 if (key !== "type") {181 if (key !== "type") {
185 nextObject[key] = child;182 nextObject[key] = child;
packages/effect-acp/src/agent.ts+3-1
...@@ -207,7 +207,9 @@ export interface AcpAgentShape {...@@ -207,7 +207,9 @@ export interface AcpAgentShape {
207 ) => Effect.Effect<void>;207 ) => Effect.Effect<void>;
208}208}
209209
210export class AcpAgent extends Context.Service<AcpAgent, AcpAgentShape>()("effect-acp/AcpAgent") {}210export class AcpAgent extends Context.Service<AcpAgent, AcpAgentShape>()(
211 "effect-acp/agent/AcpAgent",
212) {}
211213
212interface AcpCoreAgentRequestHandlers {214interface AcpCoreAgentRequestHandlers {
213 initialize?: (215 initialize?: (
packages/effect-acp/src/client.ts+1-1
...@@ -263,7 +263,7 @@ export interface AcpClientShape {...@@ -263,7 +263,7 @@ export interface AcpClientShape {
263}263}
264264
265export class AcpClient extends Context.Service<AcpClient, AcpClientShape>()(265export class AcpClient extends Context.Service<AcpClient, AcpClientShape>()(
266 "effect-acp/AcpClient",266 "effect-acp/client/AcpClient",
267) {}267) {}
268268
269interface AcpCoreRequestHandlers {269interface AcpCoreRequestHandlers {
packages/effect-acp/src/protocol.ts+2-2
...@@ -29,12 +29,12 @@ export type AcpIncomingNotification =...@@ -29,12 +29,12 @@ export type AcpIncomingNotification =
29 | {29 | {
30 readonly _tag: "SessionUpdate";30 readonly _tag: "SessionUpdate";
31 readonly method: typeof CLIENT_METHODS.session_update;31 readonly method: typeof CLIENT_METHODS.session_update;
32 readonly params: typeof AcpSchema.SessionNotification.Type;32 readonly params: AcpSchema.SessionNotification;
33 }33 }
34 | {34 | {
35 readonly _tag: "ElicitationComplete";35 readonly _tag: "ElicitationComplete";
36 readonly method: typeof CLIENT_METHODS.session_elicitation_complete;36 readonly method: typeof CLIENT_METHODS.session_elicitation_complete;
37 readonly params: typeof AcpSchema.ElicitationCompleteNotification.Type;37 readonly params: AcpSchema.ElicitationCompleteNotification;
38 }38 }
39 | {39 | {
40 readonly _tag: "ExtNotification";40 readonly _tag: "ExtNotification";
packages/effect-acp/tsconfig.json+3-1
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1{1{
2 "extends": "../../tsconfig.base.json",2 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},3 "compilerOptions": {
4 "types": ["node"]
5 },
4 "include": ["src", "scripts", "test"]6 "include": ["src", "scripts", "test"]
5}7}
packages/effect-codex-app-server/package.json+2-3
...@@ -25,7 +25,7 @@...@@ -25,7 +25,7 @@
25 }25 }
26 },26 },
27 "scripts": {27 "scripts": {
28 "typecheck": "tsc --noEmit",28 "typecheck": "tsgo --noEmit",
29 "test": "vitest run",29 "test": "vitest run",
30 "generate": "bun run scripts/generate.ts",30 "generate": "bun run scripts/generate.ts",
31 "probe": "bun run test/examples/codex-app-server-probe.ts"31 "probe": "bun run test/examples/codex-app-server-probe.ts"
...@@ -34,11 +34,10 @@...@@ -34,11 +34,10 @@
34 "effect": "catalog:"34 "effect": "catalog:"
35 },35 },
36 "devDependencies": {36 "devDependencies": {
37 "@effect/language-service": "catalog:",
38 "@effect/openapi-generator": "catalog:",37 "@effect/openapi-generator": "catalog:",
39 "@effect/platform-node": "catalog:",38 "@effect/platform-node": "catalog:",
40 "@effect/vitest": "catalog:",39 "@effect/vitest": "catalog:",
41 "typescript": "catalog:",40 "@types/node": "catalog:",
42 "vitest": "catalog:"41 "vitest": "catalog:"
43 }42 }
44}43}
packages/effect-codex-app-server/scripts/generate.ts+12-15
...@@ -70,7 +70,7 @@ class GeneratorError extends Schema.TaggedErrorClass<GeneratorError>()("Generato...@@ -70,7 +70,7 @@ class GeneratorError extends Schema.TaggedErrorClass<GeneratorError>()("Generato
70 }70 }
71}71}
7272
73const ManualSchemas: Record<string, typeof Schema.Json.Type> = {73const ManualSchemas: Record<string, Schema.Json> = {
74 GetAuthStatusParams: {74 GetAuthStatusParams: {
75 type: "object",75 type: "object",
76 title: "GetAuthStatusParams",76 title: "GetAuthStatusParams",
...@@ -218,7 +218,7 @@ function collectSchemaEntries(...@@ -218,7 +218,7 @@ function collectSchemaEntries(
218 return entries;218 return entries;
219}219}
220220
221function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.Json.Type {221function normalizeNullableTypes(value: Schema.Json): Schema.Json {
222 if (Array.isArray(value)) {222 if (Array.isArray(value)) {
223 return value.map(normalizeNullableTypes);223 return value.map(normalizeNullableTypes);
224 }224 }
...@@ -230,10 +230,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J...@@ -230,10 +230,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
230 key,230 key,
231 normalizeNullableTypes(child),231 normalizeNullableTypes(child),
232 ]);232 ]);
233 const normalizedObject = Object.fromEntries(normalizedEntries) as Record<233 const normalizedObject = Object.fromEntries(normalizedEntries) as Record<string, Schema.Json>;
234 string,
235 typeof Schema.Json.Type
236 >;
237 const typeValue = normalizedObject.type;234 const typeValue = normalizedObject.type;
238235
239 if (!Array.isArray(typeValue)) {236 if (!Array.isArray(typeValue)) {
...@@ -251,7 +248,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J...@@ -251,7 +248,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
251 }248 }
252 const nonNullType = nonNullTypes[0]!;249 const nonNullType = nonNullTypes[0]!;
253250
254 const nextObject: Record<string, typeof Schema.Json.Type> = {};251 const nextObject: Record<string, Schema.Json> = {};
255 for (const [key, child] of Object.entries(normalizedObject)) {252 for (const [key, child] of Object.entries(normalizedObject)) {
256 if (key !== "type") {253 if (key !== "type") {
257 nextObject[key] = child;254 nextObject[key] = child;
...@@ -269,7 +266,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J...@@ -269,7 +266,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
269 };266 };
270}267}
271268
272function stripNullDefaults(value: typeof Schema.Json.Type): typeof Schema.Json.Type {269function stripNullDefaults(value: Schema.Json): Schema.Json {
273 if (Array.isArray(value)) {270 if (Array.isArray(value)) {
274 return value.map(stripNullDefaults);271 return value.map(stripNullDefaults);
275 }272 }
...@@ -281,7 +278,7 @@ function stripNullDefaults(value: typeof Schema.Json.Type): typeof Schema.Json.T...@@ -281,7 +278,7 @@ function stripNullDefaults(value: typeof Schema.Json.Type): typeof Schema.Json.T
281 Object.entries(value)278 Object.entries(value)
282 .filter(([key, child]) => !(key === "default" && child === null))279 .filter(([key, child]) => !(key === "default" && child === null))
283 .map(([key, child]) => [key, stripNullDefaults(child)]),280 .map(([key, child]) => [key, stripNullDefaults(child)]),
284 ) as typeof Schema.Json.Type;281 ) as Schema.Json;
285}282}
286283
287function toPascalCaseMethod(method: string) {284function toPascalCaseMethod(method: string) {
...@@ -417,7 +414,7 @@ function renderSchemaMap(...@@ -417,7 +414,7 @@ function renderSchemaMap(
417}414}
418415
419function renderSchemaTypeReference(schemaName: string) {416function renderSchemaTypeReference(schemaName: string) {
420 return schemaName === "undefined" ? "undefined" : `typeof CodexSchema.${schemaName}.Type`;417 return schemaName === "undefined" ? "undefined" : `CodexSchema.${schemaName}`;
421}418}
422419
423function exportNameForPath(filePath: string): string {420function exportNameForPath(filePath: string): string {
...@@ -468,11 +465,11 @@ function buildJsonSchemaFiles(...@@ -468,11 +465,11 @@ function buildJsonSchemaFiles(
468}465}
469466
470function rewriteExternalRefs(467function rewriteExternalRefs(
471 value: typeof Schema.Json.Type,468 value: Schema.Json,
472 localDefinitionNames: ReadonlyMap<string, string>,469 localDefinitionNames: ReadonlyMap<string, string>,
473 currentNamespace: string | undefined,470 currentNamespace: string | undefined,
474 exportNameByQualifiedName: ReadonlyMap<string, string>,471 exportNameByQualifiedName: ReadonlyMap<string, string>,
475): typeof Schema.Json.Type {472): Schema.Json {
476 if (Array.isArray(value)) {473 if (Array.isArray(value)) {
477 return value.map((entry) =>474 return value.map((entry) =>
478 rewriteExternalRefs(entry, localDefinitionNames, currentNamespace, exportNameByQualifiedName),475 rewriteExternalRefs(entry, localDefinitionNames, currentNamespace, exportNameByQualifiedName),
...@@ -522,7 +519,7 @@ function rewriteExternalRefs(...@@ -522,7 +519,7 @@ function rewriteExternalRefs(
522 ),519 ),
523 ];520 ];
524 }),521 }),
525 ) as typeof Schema.Json.Type;522 ) as Schema.Json;
526}523}
527524
528const generateFiles = Effect.fn("generateFiles")(function* () {525const generateFiles = Effect.fn("generateFiles")(function* () {
...@@ -543,7 +540,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () {...@@ -543,7 +540,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () {
543 const exportNameByQualifiedName = new Map(540 const exportNameByQualifiedName = new Map(
544 jsonSchemaFiles.map((file) => [file.qualifiedName, file.exportName]),541 jsonSchemaFiles.map((file) => [file.qualifiedName, file.exportName]),
545 );542 );
546 const aggregateSchemas: Record<string, typeof Schema.Json.Type> = {};543 const aggregateSchemas: Record<string, Schema.Json> = {};
547544
548 for (const file of jsonSchemaFiles) {545 for (const file of jsonSchemaFiles) {
549 const raw = yield* fetchText(file.downloadUrl);546 const raw = yield* fetchText(file.downloadUrl);
...@@ -568,7 +565,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () {...@@ -568,7 +565,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () {
568 );565 );
569 }566 }
570567
571 const topLevelSchema: Record<string, typeof Schema.Json.Type> = {};568 const topLevelSchema: Record<string, Schema.Json> = {};
572 for (const [key, value] of Object.entries(parsed)) {569 for (const [key, value] of Object.entries(parsed)) {
573 if (key !== "definitions") {570 if (key !== "definitions") {
574 topLevelSchema[key] = value;571 topLevelSchema[key] = value;
packages/effect-codex-app-server/src/_generated/meta.gen.ts+233-233
...@@ -173,165 +173,165 @@ export type ServerRequestMethod = keyof typeof SERVER_REQUEST_METHODS;...@@ -173,165 +173,165 @@ export type ServerRequestMethod = keyof typeof SERVER_REQUEST_METHODS;
173export type ServerNotificationMethod = keyof typeof SERVER_NOTIFICATION_METHODS;173export type ServerNotificationMethod = keyof typeof SERVER_NOTIFICATION_METHODS;
174174
175export interface ClientRequestParamsByMethod {175export interface ClientRequestParamsByMethod {
176 readonly initialize: typeof CodexSchema.V1InitializeParams.Type;176 readonly initialize: CodexSchema.V1InitializeParams;
177 readonly "thread/start": typeof CodexSchema.V2ThreadStartParams.Type;177 readonly "thread/start": CodexSchema.V2ThreadStartParams;
178 readonly "thread/resume": typeof CodexSchema.V2ThreadResumeParams.Type;178 readonly "thread/resume": CodexSchema.V2ThreadResumeParams;
179 readonly "thread/fork": typeof CodexSchema.V2ThreadForkParams.Type;179 readonly "thread/fork": CodexSchema.V2ThreadForkParams;
180 readonly "thread/archive": typeof CodexSchema.V2ThreadArchiveParams.Type;180 readonly "thread/archive": CodexSchema.V2ThreadArchiveParams;
181 readonly "thread/unsubscribe": typeof CodexSchema.V2ThreadUnsubscribeParams.Type;181 readonly "thread/unsubscribe": CodexSchema.V2ThreadUnsubscribeParams;
182 readonly "thread/name/set": typeof CodexSchema.V2ThreadSetNameParams.Type;182 readonly "thread/name/set": CodexSchema.V2ThreadSetNameParams;
183 readonly "thread/metadata/update": typeof CodexSchema.V2ThreadMetadataUpdateParams.Type;183 readonly "thread/metadata/update": CodexSchema.V2ThreadMetadataUpdateParams;
184 readonly "thread/unarchive": typeof CodexSchema.V2ThreadUnarchiveParams.Type;184 readonly "thread/unarchive": CodexSchema.V2ThreadUnarchiveParams;
185 readonly "thread/compact/start": typeof CodexSchema.V2ThreadCompactStartParams.Type;185 readonly "thread/compact/start": CodexSchema.V2ThreadCompactStartParams;
186 readonly "thread/shellCommand": typeof CodexSchema.V2ThreadShellCommandParams.Type;186 readonly "thread/shellCommand": CodexSchema.V2ThreadShellCommandParams;
187 readonly "thread/approveGuardianDeniedAction": typeof CodexSchema.V2ThreadApproveGuardianDeniedActionParams.Type;187 readonly "thread/approveGuardianDeniedAction": CodexSchema.V2ThreadApproveGuardianDeniedActionParams;
188 readonly "thread/rollback": typeof CodexSchema.V2ThreadRollbackParams.Type;188 readonly "thread/rollback": CodexSchema.V2ThreadRollbackParams;
189 readonly "thread/list": typeof CodexSchema.V2ThreadListParams.Type;189 readonly "thread/list": CodexSchema.V2ThreadListParams;
190 readonly "thread/loaded/list": typeof CodexSchema.V2ThreadLoadedListParams.Type;190 readonly "thread/loaded/list": CodexSchema.V2ThreadLoadedListParams;
191 readonly "thread/read": typeof CodexSchema.V2ThreadReadParams.Type;191 readonly "thread/read": CodexSchema.V2ThreadReadParams;
192 readonly "thread/inject_items": typeof CodexSchema.V2ThreadInjectItemsParams.Type;192 readonly "thread/inject_items": CodexSchema.V2ThreadInjectItemsParams;
193 readonly "skills/list": typeof CodexSchema.V2SkillsListParams.Type;193 readonly "skills/list": CodexSchema.V2SkillsListParams;
194 readonly "hooks/list": typeof CodexSchema.V2HooksListParams.Type;194 readonly "hooks/list": CodexSchema.V2HooksListParams;
195 readonly "marketplace/add": typeof CodexSchema.V2MarketplaceAddParams.Type;195 readonly "marketplace/add": CodexSchema.V2MarketplaceAddParams;
196 readonly "marketplace/remove": typeof CodexSchema.V2MarketplaceRemoveParams.Type;196 readonly "marketplace/remove": CodexSchema.V2MarketplaceRemoveParams;
197 readonly "marketplace/upgrade": typeof CodexSchema.V2MarketplaceUpgradeParams.Type;197 readonly "marketplace/upgrade": CodexSchema.V2MarketplaceUpgradeParams;
198 readonly "plugin/list": typeof CodexSchema.V2PluginListParams.Type;198 readonly "plugin/list": CodexSchema.V2PluginListParams;
199 readonly "plugin/read": typeof CodexSchema.V2PluginReadParams.Type;199 readonly "plugin/read": CodexSchema.V2PluginReadParams;
200 readonly "plugin/skill/read": typeof CodexSchema.V2PluginSkillReadParams.Type;200 readonly "plugin/skill/read": CodexSchema.V2PluginSkillReadParams;
201 readonly "plugin/share/save": typeof CodexSchema.V2PluginShareSaveParams.Type;201 readonly "plugin/share/save": CodexSchema.V2PluginShareSaveParams;
202 readonly "plugin/share/updateTargets": typeof CodexSchema.V2PluginShareUpdateTargetsParams.Type;202 readonly "plugin/share/updateTargets": CodexSchema.V2PluginShareUpdateTargetsParams;
203 readonly "plugin/share/list": typeof CodexSchema.V2PluginShareListParams.Type;203 readonly "plugin/share/list": CodexSchema.V2PluginShareListParams;
204 readonly "plugin/share/delete": typeof CodexSchema.V2PluginShareDeleteParams.Type;204 readonly "plugin/share/delete": CodexSchema.V2PluginShareDeleteParams;
205 readonly "app/list": typeof CodexSchema.V2AppsListParams.Type;205 readonly "app/list": CodexSchema.V2AppsListParams;
206 readonly "fs/readFile": typeof CodexSchema.V2FsReadFileParams.Type;206 readonly "fs/readFile": CodexSchema.V2FsReadFileParams;
207 readonly "fs/writeFile": typeof CodexSchema.V2FsWriteFileParams.Type;207 readonly "fs/writeFile": CodexSchema.V2FsWriteFileParams;
208 readonly "fs/createDirectory": typeof CodexSchema.V2FsCreateDirectoryParams.Type;208 readonly "fs/createDirectory": CodexSchema.V2FsCreateDirectoryParams;
209 readonly "fs/getMetadata": typeof CodexSchema.V2FsGetMetadataParams.Type;209 readonly "fs/getMetadata": CodexSchema.V2FsGetMetadataParams;
210 readonly "fs/readDirectory": typeof CodexSchema.V2FsReadDirectoryParams.Type;210 readonly "fs/readDirectory": CodexSchema.V2FsReadDirectoryParams;
211 readonly "fs/remove": typeof CodexSchema.V2FsRemoveParams.Type;211 readonly "fs/remove": CodexSchema.V2FsRemoveParams;
212 readonly "fs/copy": typeof CodexSchema.V2FsCopyParams.Type;212 readonly "fs/copy": CodexSchema.V2FsCopyParams;
213 readonly "fs/watch": typeof CodexSchema.V2FsWatchParams.Type;213 readonly "fs/watch": CodexSchema.V2FsWatchParams;
214 readonly "fs/unwatch": typeof CodexSchema.V2FsUnwatchParams.Type;214 readonly "fs/unwatch": CodexSchema.V2FsUnwatchParams;
215 readonly "skills/config/write": typeof CodexSchema.V2SkillsConfigWriteParams.Type;215 readonly "skills/config/write": CodexSchema.V2SkillsConfigWriteParams;
216 readonly "plugin/install": typeof CodexSchema.V2PluginInstallParams.Type;216 readonly "plugin/install": CodexSchema.V2PluginInstallParams;
217 readonly "plugin/uninstall": typeof CodexSchema.V2PluginUninstallParams.Type;217 readonly "plugin/uninstall": CodexSchema.V2PluginUninstallParams;
218 readonly "turn/start": typeof CodexSchema.V2TurnStartParams.Type;218 readonly "turn/start": CodexSchema.V2TurnStartParams;
219 readonly "turn/steer": typeof CodexSchema.V2TurnSteerParams.Type;219 readonly "turn/steer": CodexSchema.V2TurnSteerParams;
220 readonly "turn/interrupt": typeof CodexSchema.V2TurnInterruptParams.Type;220 readonly "turn/interrupt": CodexSchema.V2TurnInterruptParams;
221 readonly "review/start": typeof CodexSchema.V2ReviewStartParams.Type;221 readonly "review/start": CodexSchema.V2ReviewStartParams;
222 readonly "model/list": typeof CodexSchema.V2ModelListParams.Type;222 readonly "model/list": CodexSchema.V2ModelListParams;
223 readonly "modelProvider/capabilities/read": typeof CodexSchema.V2ModelProviderCapabilitiesReadParams.Type;223 readonly "modelProvider/capabilities/read": CodexSchema.V2ModelProviderCapabilitiesReadParams;
224 readonly "experimentalFeature/list": typeof CodexSchema.V2ExperimentalFeatureListParams.Type;224 readonly "experimentalFeature/list": CodexSchema.V2ExperimentalFeatureListParams;
225 readonly "experimentalFeature/enablement/set": typeof CodexSchema.V2ExperimentalFeatureEnablementSetParams.Type;225 readonly "experimentalFeature/enablement/set": CodexSchema.V2ExperimentalFeatureEnablementSetParams;
226 readonly "mcpServer/oauth/login": typeof CodexSchema.V2McpServerOauthLoginParams.Type;226 readonly "mcpServer/oauth/login": CodexSchema.V2McpServerOauthLoginParams;
227 readonly "config/mcpServer/reload": undefined;227 readonly "config/mcpServer/reload": undefined;
228 readonly "mcpServerStatus/list": typeof CodexSchema.V2ListMcpServerStatusParams.Type;228 readonly "mcpServerStatus/list": CodexSchema.V2ListMcpServerStatusParams;
229 readonly "mcpServer/resource/read": typeof CodexSchema.V2McpResourceReadParams.Type;229 readonly "mcpServer/resource/read": CodexSchema.V2McpResourceReadParams;
230 readonly "mcpServer/tool/call": typeof CodexSchema.V2McpServerToolCallParams.Type;230 readonly "mcpServer/tool/call": CodexSchema.V2McpServerToolCallParams;
231 readonly "windowsSandbox/setupStart": typeof CodexSchema.V2WindowsSandboxSetupStartParams.Type;231 readonly "windowsSandbox/setupStart": CodexSchema.V2WindowsSandboxSetupStartParams;
232 readonly "windowsSandbox/readiness": undefined;232 readonly "windowsSandbox/readiness": undefined;
233 readonly "account/login/start": typeof CodexSchema.V2LoginAccountParams.Type;233 readonly "account/login/start": CodexSchema.V2LoginAccountParams;
234 readonly "account/login/cancel": typeof CodexSchema.V2CancelLoginAccountParams.Type;234 readonly "account/login/cancel": CodexSchema.V2CancelLoginAccountParams;
235 readonly "account/logout": undefined;235 readonly "account/logout": undefined;
236 readonly "account/rateLimits/read": undefined;236 readonly "account/rateLimits/read": undefined;
237 readonly "account/sendAddCreditsNudgeEmail": typeof CodexSchema.V2SendAddCreditsNudgeEmailParams.Type;237 readonly "account/sendAddCreditsNudgeEmail": CodexSchema.V2SendAddCreditsNudgeEmailParams;
238 readonly "feedback/upload": typeof CodexSchema.V2FeedbackUploadParams.Type;238 readonly "feedback/upload": CodexSchema.V2FeedbackUploadParams;
239 readonly "command/exec": typeof CodexSchema.V2CommandExecParams.Type;239 readonly "command/exec": CodexSchema.V2CommandExecParams;
240 readonly "command/exec/write": typeof CodexSchema.V2CommandExecWriteParams.Type;240 readonly "command/exec/write": CodexSchema.V2CommandExecWriteParams;
241 readonly "command/exec/terminate": typeof CodexSchema.V2CommandExecTerminateParams.Type;241 readonly "command/exec/terminate": CodexSchema.V2CommandExecTerminateParams;
242 readonly "command/exec/resize": typeof CodexSchema.V2CommandExecResizeParams.Type;242 readonly "command/exec/resize": CodexSchema.V2CommandExecResizeParams;
243 readonly "config/read": typeof CodexSchema.V2ConfigReadParams.Type;243 readonly "config/read": CodexSchema.V2ConfigReadParams;
244 readonly "externalAgentConfig/detect": typeof CodexSchema.V2ExternalAgentConfigDetectParams.Type;244 readonly "externalAgentConfig/detect": CodexSchema.V2ExternalAgentConfigDetectParams;
245 readonly "externalAgentConfig/import": typeof CodexSchema.V2ExternalAgentConfigImportParams.Type;245 readonly "externalAgentConfig/import": CodexSchema.V2ExternalAgentConfigImportParams;
246 readonly "config/value/write": typeof CodexSchema.V2ConfigValueWriteParams.Type;246 readonly "config/value/write": CodexSchema.V2ConfigValueWriteParams;
247 readonly "config/batchWrite": typeof CodexSchema.V2ConfigBatchWriteParams.Type;247 readonly "config/batchWrite": CodexSchema.V2ConfigBatchWriteParams;
248 readonly "configRequirements/read": undefined;248 readonly "configRequirements/read": undefined;
249 readonly "account/read": typeof CodexSchema.V2GetAccountParams.Type;249 readonly "account/read": CodexSchema.V2GetAccountParams;
250 readonly getConversationSummary: typeof CodexSchema.GetConversationSummaryParams.Type;250 readonly getConversationSummary: CodexSchema.GetConversationSummaryParams;
251 readonly gitDiffToRemote: typeof CodexSchema.GitDiffToRemoteParams.Type;251 readonly gitDiffToRemote: CodexSchema.GitDiffToRemoteParams;
252 readonly getAuthStatus: typeof CodexSchema.GetAuthStatusParams.Type;252 readonly getAuthStatus: CodexSchema.GetAuthStatusParams;
253 readonly fuzzyFileSearch: typeof CodexSchema.FuzzyFileSearchParams.Type;253 readonly fuzzyFileSearch: CodexSchema.FuzzyFileSearchParams;
254}254}
255255
256export interface ClientRequestResponsesByMethod {256export interface ClientRequestResponsesByMethod {
257 readonly initialize: typeof CodexSchema.V1InitializeResponse.Type;257 readonly initialize: CodexSchema.V1InitializeResponse;
258 readonly "thread/start": typeof CodexSchema.V2ThreadStartResponse.Type;258 readonly "thread/start": CodexSchema.V2ThreadStartResponse;
259 readonly "thread/resume": typeof CodexSchema.V2ThreadResumeResponse.Type;259 readonly "thread/resume": CodexSchema.V2ThreadResumeResponse;
260 readonly "thread/fork": typeof CodexSchema.V2ThreadForkResponse.Type;260 readonly "thread/fork": CodexSchema.V2ThreadForkResponse;
261 readonly "thread/archive": typeof CodexSchema.V2ThreadArchiveResponse.Type;261 readonly "thread/archive": CodexSchema.V2ThreadArchiveResponse;
262 readonly "thread/unsubscribe": typeof CodexSchema.V2ThreadUnsubscribeResponse.Type;262 readonly "thread/unsubscribe": CodexSchema.V2ThreadUnsubscribeResponse;
263 readonly "thread/name/set": typeof CodexSchema.V2ThreadSetNameResponse.Type;263 readonly "thread/name/set": CodexSchema.V2ThreadSetNameResponse;
264 readonly "thread/metadata/update": typeof CodexSchema.V2ThreadMetadataUpdateResponse.Type;264 readonly "thread/metadata/update": CodexSchema.V2ThreadMetadataUpdateResponse;
265 readonly "thread/unarchive": typeof CodexSchema.V2ThreadUnarchiveResponse.Type;265 readonly "thread/unarchive": CodexSchema.V2ThreadUnarchiveResponse;
266 readonly "thread/compact/start": typeof CodexSchema.V2ThreadCompactStartResponse.Type;266 readonly "thread/compact/start": CodexSchema.V2ThreadCompactStartResponse;
267 readonly "thread/shellCommand": typeof CodexSchema.V2ThreadShellCommandResponse.Type;267 readonly "thread/shellCommand": CodexSchema.V2ThreadShellCommandResponse;
268 readonly "thread/approveGuardianDeniedAction": typeof CodexSchema.V2ThreadApproveGuardianDeniedActionResponse.Type;268 readonly "thread/approveGuardianDeniedAction": CodexSchema.V2ThreadApproveGuardianDeniedActionResponse;
269 readonly "thread/rollback": typeof CodexSchema.V2ThreadRollbackResponse.Type;269 readonly "thread/rollback": CodexSchema.V2ThreadRollbackResponse;
270 readonly "thread/list": typeof CodexSchema.V2ThreadListResponse.Type;270 readonly "thread/list": CodexSchema.V2ThreadListResponse;
271 readonly "thread/loaded/list": typeof CodexSchema.V2ThreadLoadedListResponse.Type;271 readonly "thread/loaded/list": CodexSchema.V2ThreadLoadedListResponse;
272 readonly "thread/read": typeof CodexSchema.V2ThreadReadResponse.Type;272 readonly "thread/read": CodexSchema.V2ThreadReadResponse;
273 readonly "thread/inject_items": typeof CodexSchema.V2ThreadInjectItemsResponse.Type;273 readonly "thread/inject_items": CodexSchema.V2ThreadInjectItemsResponse;
274 readonly "skills/list": typeof CodexSchema.V2SkillsListResponse.Type;274 readonly "skills/list": CodexSchema.V2SkillsListResponse;
275 readonly "hooks/list": typeof CodexSchema.V2HooksListResponse.Type;275 readonly "hooks/list": CodexSchema.V2HooksListResponse;
276 readonly "marketplace/add": typeof CodexSchema.V2MarketplaceAddResponse.Type;276 readonly "marketplace/add": CodexSchema.V2MarketplaceAddResponse;
277 readonly "marketplace/remove": typeof CodexSchema.V2MarketplaceRemoveResponse.Type;277 readonly "marketplace/remove": CodexSchema.V2MarketplaceRemoveResponse;
278 readonly "marketplace/upgrade": typeof CodexSchema.V2MarketplaceUpgradeResponse.Type;278 readonly "marketplace/upgrade": CodexSchema.V2MarketplaceUpgradeResponse;
279 readonly "plugin/list": typeof CodexSchema.V2PluginListResponse.Type;279 readonly "plugin/list": CodexSchema.V2PluginListResponse;
280 readonly "plugin/read": typeof CodexSchema.V2PluginReadResponse.Type;280 readonly "plugin/read": CodexSchema.V2PluginReadResponse;
281 readonly "plugin/skill/read": typeof CodexSchema.V2PluginSkillReadResponse.Type;281 readonly "plugin/skill/read": CodexSchema.V2PluginSkillReadResponse;
282 readonly "plugin/share/save": typeof CodexSchema.V2PluginShareSaveResponse.Type;282 readonly "plugin/share/save": CodexSchema.V2PluginShareSaveResponse;
283 readonly "plugin/share/updateTargets": typeof CodexSchema.V2PluginShareUpdateTargetsResponse.Type;283 readonly "plugin/share/updateTargets": CodexSchema.V2PluginShareUpdateTargetsResponse;
284 readonly "plugin/share/list": typeof CodexSchema.V2PluginShareListResponse.Type;284 readonly "plugin/share/list": CodexSchema.V2PluginShareListResponse;
285 readonly "plugin/share/delete": typeof CodexSchema.V2PluginShareDeleteResponse.Type;285 readonly "plugin/share/delete": CodexSchema.V2PluginShareDeleteResponse;
286 readonly "app/list": typeof CodexSchema.V2AppsListResponse.Type;286 readonly "app/list": CodexSchema.V2AppsListResponse;
287 readonly "fs/readFile": typeof CodexSchema.V2FsReadFileResponse.Type;287 readonly "fs/readFile": CodexSchema.V2FsReadFileResponse;
288 readonly "fs/writeFile": typeof CodexSchema.V2FsWriteFileResponse.Type;288 readonly "fs/writeFile": CodexSchema.V2FsWriteFileResponse;
289 readonly "fs/createDirectory": typeof CodexSchema.V2FsCreateDirectoryResponse.Type;289 readonly "fs/createDirectory": CodexSchema.V2FsCreateDirectoryResponse;
290 readonly "fs/getMetadata": typeof CodexSchema.V2FsGetMetadataResponse.Type;290 readonly "fs/getMetadata": CodexSchema.V2FsGetMetadataResponse;
291 readonly "fs/readDirectory": typeof CodexSchema.V2FsReadDirectoryResponse.Type;291 readonly "fs/readDirectory": CodexSchema.V2FsReadDirectoryResponse;
292 readonly "fs/remove": typeof CodexSchema.V2FsRemoveResponse.Type;292 readonly "fs/remove": CodexSchema.V2FsRemoveResponse;
293 readonly "fs/copy": typeof CodexSchema.V2FsCopyResponse.Type;293 readonly "fs/copy": CodexSchema.V2FsCopyResponse;
294 readonly "fs/watch": typeof CodexSchema.V2FsWatchResponse.Type;294 readonly "fs/watch": CodexSchema.V2FsWatchResponse;
295 readonly "fs/unwatch": typeof CodexSchema.V2FsUnwatchResponse.Type;295 readonly "fs/unwatch": CodexSchema.V2FsUnwatchResponse;
296 readonly "skills/config/write": typeof CodexSchema.V2SkillsConfigWriteResponse.Type;296 readonly "skills/config/write": CodexSchema.V2SkillsConfigWriteResponse;
297 readonly "plugin/install": typeof CodexSchema.V2PluginInstallResponse.Type;297 readonly "plugin/install": CodexSchema.V2PluginInstallResponse;
298 readonly "plugin/uninstall": typeof CodexSchema.V2PluginUninstallResponse.Type;298 readonly "plugin/uninstall": CodexSchema.V2PluginUninstallResponse;
299 readonly "turn/start": typeof CodexSchema.V2TurnStartResponse.Type;299 readonly "turn/start": CodexSchema.V2TurnStartResponse;
300 readonly "turn/steer": typeof CodexSchema.V2TurnSteerResponse.Type;300 readonly "turn/steer": CodexSchema.V2TurnSteerResponse;
301 readonly "turn/interrupt": typeof CodexSchema.V2TurnInterruptResponse.Type;301 readonly "turn/interrupt": CodexSchema.V2TurnInterruptResponse;
302 readonly "review/start": typeof CodexSchema.V2ReviewStartResponse.Type;302 readonly "review/start": CodexSchema.V2ReviewStartResponse;
303 readonly "model/list": typeof CodexSchema.V2ModelListResponse.Type;303 readonly "model/list": CodexSchema.V2ModelListResponse;
304 readonly "modelProvider/capabilities/read": typeof CodexSchema.V2ModelProviderCapabilitiesReadResponse.Type;304 readonly "modelProvider/capabilities/read": CodexSchema.V2ModelProviderCapabilitiesReadResponse;
305 readonly "experimentalFeature/list": typeof CodexSchema.V2ExperimentalFeatureListResponse.Type;305 readonly "experimentalFeature/list": CodexSchema.V2ExperimentalFeatureListResponse;
306 readonly "experimentalFeature/enablement/set": typeof CodexSchema.V2ExperimentalFeatureEnablementSetResponse.Type;306 readonly "experimentalFeature/enablement/set": CodexSchema.V2ExperimentalFeatureEnablementSetResponse;
307 readonly "mcpServer/oauth/login": typeof CodexSchema.V2McpServerOauthLoginResponse.Type;307 readonly "mcpServer/oauth/login": CodexSchema.V2McpServerOauthLoginResponse;
308 readonly "config/mcpServer/reload": typeof CodexSchema.V2McpServerRefreshResponse.Type;308 readonly "config/mcpServer/reload": CodexSchema.V2McpServerRefreshResponse;
309 readonly "mcpServerStatus/list": typeof CodexSchema.V2ListMcpServerStatusResponse.Type;309 readonly "mcpServerStatus/list": CodexSchema.V2ListMcpServerStatusResponse;
310 readonly "mcpServer/resource/read": typeof CodexSchema.V2McpResourceReadResponse.Type;310 readonly "mcpServer/resource/read": CodexSchema.V2McpResourceReadResponse;
311 readonly "mcpServer/tool/call": typeof CodexSchema.V2McpServerToolCallResponse.Type;311 readonly "mcpServer/tool/call": CodexSchema.V2McpServerToolCallResponse;
312 readonly "windowsSandbox/setupStart": typeof CodexSchema.V2WindowsSandboxSetupStartResponse.Type;312 readonly "windowsSandbox/setupStart": CodexSchema.V2WindowsSandboxSetupStartResponse;
313 readonly "windowsSandbox/readiness": typeof CodexSchema.V2WindowsSandboxReadinessResponse.Type;313 readonly "windowsSandbox/readiness": CodexSchema.V2WindowsSandboxReadinessResponse;
314 readonly "account/login/start": typeof CodexSchema.V2LoginAccountResponse.Type;314 readonly "account/login/start": CodexSchema.V2LoginAccountResponse;
315 readonly "account/login/cancel": typeof CodexSchema.V2CancelLoginAccountResponse.Type;315 readonly "account/login/cancel": CodexSchema.V2CancelLoginAccountResponse;
316 readonly "account/logout": typeof CodexSchema.V2LogoutAccountResponse.Type;316 readonly "account/logout": CodexSchema.V2LogoutAccountResponse;
317 readonly "account/rateLimits/read": typeof CodexSchema.V2GetAccountRateLimitsResponse.Type;317 readonly "account/rateLimits/read": CodexSchema.V2GetAccountRateLimitsResponse;
318 readonly "account/sendAddCreditsNudgeEmail": typeof CodexSchema.V2SendAddCreditsNudgeEmailResponse.Type;318 readonly "account/sendAddCreditsNudgeEmail": CodexSchema.V2SendAddCreditsNudgeEmailResponse;
319 readonly "feedback/upload": typeof CodexSchema.V2FeedbackUploadResponse.Type;319 readonly "feedback/upload": CodexSchema.V2FeedbackUploadResponse;
320 readonly "command/exec": typeof CodexSchema.V2CommandExecResponse.Type;320 readonly "command/exec": CodexSchema.V2CommandExecResponse;
321 readonly "command/exec/write": typeof CodexSchema.V2CommandExecWriteResponse.Type;321 readonly "command/exec/write": CodexSchema.V2CommandExecWriteResponse;
322 readonly "command/exec/terminate": typeof CodexSchema.V2CommandExecTerminateResponse.Type;322 readonly "command/exec/terminate": CodexSchema.V2CommandExecTerminateResponse;
323 readonly "command/exec/resize": typeof CodexSchema.V2CommandExecResizeResponse.Type;323 readonly "command/exec/resize": CodexSchema.V2CommandExecResizeResponse;
324 readonly "config/read": typeof CodexSchema.V2ConfigReadResponse.Type;324 readonly "config/read": CodexSchema.V2ConfigReadResponse;
325 readonly "externalAgentConfig/detect": typeof CodexSchema.V2ExternalAgentConfigDetectResponse.Type;325 readonly "externalAgentConfig/detect": CodexSchema.V2ExternalAgentConfigDetectResponse;
326 readonly "externalAgentConfig/import": typeof CodexSchema.V2ExternalAgentConfigImportResponse.Type;326 readonly "externalAgentConfig/import": CodexSchema.V2ExternalAgentConfigImportResponse;
327 readonly "config/value/write": typeof CodexSchema.V2ConfigWriteResponse.Type;327 readonly "config/value/write": CodexSchema.V2ConfigWriteResponse;
328 readonly "config/batchWrite": typeof CodexSchema.V2ConfigWriteResponse.Type;328 readonly "config/batchWrite": CodexSchema.V2ConfigWriteResponse;
329 readonly "configRequirements/read": typeof CodexSchema.V2ConfigRequirementsReadResponse.Type;329 readonly "configRequirements/read": CodexSchema.V2ConfigRequirementsReadResponse;
330 readonly "account/read": typeof CodexSchema.V2GetAccountResponse.Type;330 readonly "account/read": CodexSchema.V2GetAccountResponse;
331 readonly getConversationSummary: typeof CodexSchema.GetConversationSummaryResponse.Type;331 readonly getConversationSummary: CodexSchema.GetConversationSummaryResponse;
332 readonly gitDiffToRemote: typeof CodexSchema.GitDiffToRemoteResponse.Type;332 readonly gitDiffToRemote: CodexSchema.GitDiffToRemoteResponse;
333 readonly getAuthStatus: typeof CodexSchema.GetAuthStatusResponse.Type;333 readonly getAuthStatus: CodexSchema.GetAuthStatusResponse;
334 readonly fuzzyFileSearch: typeof CodexSchema.FuzzyFileSearchResponse.Type;334 readonly fuzzyFileSearch: CodexSchema.FuzzyFileSearchResponse;
335}335}
336336
337export interface ClientNotificationParamsByMethod {337export interface ClientNotificationParamsByMethod {
...@@ -339,94 +339,94 @@ export interface ClientNotificationParamsByMethod {...@@ -339,94 +339,94 @@ export interface ClientNotificationParamsByMethod {
339}339}
340340
341export interface ServerRequestParamsByMethod {341export interface ServerRequestParamsByMethod {
342 readonly "item/commandExecution/requestApproval": typeof CodexSchema.CommandExecutionRequestApprovalParams.Type;342 readonly "item/commandExecution/requestApproval": CodexSchema.CommandExecutionRequestApprovalParams;
343 readonly "item/fileChange/requestApproval": typeof CodexSchema.FileChangeRequestApprovalParams.Type;343 readonly "item/fileChange/requestApproval": CodexSchema.FileChangeRequestApprovalParams;
344 readonly "item/tool/requestUserInput": typeof CodexSchema.ToolRequestUserInputParams.Type;344 readonly "item/tool/requestUserInput": CodexSchema.ToolRequestUserInputParams;
345 readonly "mcpServer/elicitation/request": typeof CodexSchema.McpServerElicitationRequestParams.Type;345 readonly "mcpServer/elicitation/request": CodexSchema.McpServerElicitationRequestParams;
346 readonly "item/permissions/requestApproval": typeof CodexSchema.PermissionsRequestApprovalParams.Type;346 readonly "item/permissions/requestApproval": CodexSchema.PermissionsRequestApprovalParams;
347 readonly "item/tool/call": typeof CodexSchema.DynamicToolCallParams.Type;347 readonly "item/tool/call": CodexSchema.DynamicToolCallParams;
348 readonly "account/chatgptAuthTokens/refresh": typeof CodexSchema.ChatgptAuthTokensRefreshParams.Type;348 readonly "account/chatgptAuthTokens/refresh": CodexSchema.ChatgptAuthTokensRefreshParams;
349 readonly applyPatchApproval: typeof CodexSchema.ApplyPatchApprovalParams.Type;349 readonly applyPatchApproval: CodexSchema.ApplyPatchApprovalParams;
350 readonly execCommandApproval: typeof CodexSchema.ExecCommandApprovalParams.Type;350 readonly execCommandApproval: CodexSchema.ExecCommandApprovalParams;
351}351}
352352
353export interface ServerRequestResponsesByMethod {353export interface ServerRequestResponsesByMethod {
354 readonly "item/commandExecution/requestApproval": typeof CodexSchema.CommandExecutionRequestApprovalResponse.Type;354 readonly "item/commandExecution/requestApproval": CodexSchema.CommandExecutionRequestApprovalResponse;
355 readonly "item/fileChange/requestApproval": typeof CodexSchema.FileChangeRequestApprovalResponse.Type;355 readonly "item/fileChange/requestApproval": CodexSchema.FileChangeRequestApprovalResponse;
356 readonly "item/tool/requestUserInput": typeof CodexSchema.ToolRequestUserInputResponse.Type;356 readonly "item/tool/requestUserInput": CodexSchema.ToolRequestUserInputResponse;
357 readonly "mcpServer/elicitation/request": typeof CodexSchema.McpServerElicitationRequestResponse.Type;357 readonly "mcpServer/elicitation/request": CodexSchema.McpServerElicitationRequestResponse;
358 readonly "item/permissions/requestApproval": typeof CodexSchema.PermissionsRequestApprovalResponse.Type;358 readonly "item/permissions/requestApproval": CodexSchema.PermissionsRequestApprovalResponse;
359 readonly "item/tool/call": typeof CodexSchema.DynamicToolCallResponse.Type;359 readonly "item/tool/call": CodexSchema.DynamicToolCallResponse;
360 readonly "account/chatgptAuthTokens/refresh": typeof CodexSchema.ChatgptAuthTokensRefreshResponse.Type;360 readonly "account/chatgptAuthTokens/refresh": CodexSchema.ChatgptAuthTokensRefreshResponse;
361 readonly applyPatchApproval: typeof CodexSchema.ApplyPatchApprovalResponse.Type;361 readonly applyPatchApproval: CodexSchema.ApplyPatchApprovalResponse;
362 readonly execCommandApproval: typeof CodexSchema.ExecCommandApprovalResponse.Type;362 readonly execCommandApproval: CodexSchema.ExecCommandApprovalResponse;
363}363}
364364
365export interface ServerNotificationParamsByMethod {365export interface ServerNotificationParamsByMethod {
366 readonly error: typeof CodexSchema.V2ErrorNotification.Type;366 readonly error: CodexSchema.V2ErrorNotification;
367 readonly "thread/started": typeof CodexSchema.V2ThreadStartedNotification.Type;367 readonly "thread/started": CodexSchema.V2ThreadStartedNotification;
368 readonly "thread/status/changed": typeof CodexSchema.V2ThreadStatusChangedNotification.Type;368 readonly "thread/status/changed": CodexSchema.V2ThreadStatusChangedNotification;
369 readonly "thread/archived": typeof CodexSchema.V2ThreadArchivedNotification.Type;369 readonly "thread/archived": CodexSchema.V2ThreadArchivedNotification;
370 readonly "thread/unarchived": typeof CodexSchema.V2ThreadUnarchivedNotification.Type;370 readonly "thread/unarchived": CodexSchema.V2ThreadUnarchivedNotification;
371 readonly "thread/closed": typeof CodexSchema.V2ThreadClosedNotification.Type;371 readonly "thread/closed": CodexSchema.V2ThreadClosedNotification;
372 readonly "skills/changed": typeof CodexSchema.V2SkillsChangedNotification.Type;372 readonly "skills/changed": CodexSchema.V2SkillsChangedNotification;
373 readonly "thread/name/updated": typeof CodexSchema.V2ThreadNameUpdatedNotification.Type;373 readonly "thread/name/updated": CodexSchema.V2ThreadNameUpdatedNotification;
374 readonly "thread/goal/updated": typeof CodexSchema.V2ThreadGoalUpdatedNotification.Type;374 readonly "thread/goal/updated": CodexSchema.V2ThreadGoalUpdatedNotification;
375 readonly "thread/goal/cleared": typeof CodexSchema.V2ThreadGoalClearedNotification.Type;375 readonly "thread/goal/cleared": CodexSchema.V2ThreadGoalClearedNotification;
376 readonly "thread/tokenUsage/updated": typeof CodexSchema.V2ThreadTokenUsageUpdatedNotification.Type;376 readonly "thread/tokenUsage/updated": CodexSchema.V2ThreadTokenUsageUpdatedNotification;
377 readonly "turn/started": typeof CodexSchema.V2TurnStartedNotification.Type;377 readonly "turn/started": CodexSchema.V2TurnStartedNotification;
378 readonly "hook/started": typeof CodexSchema.V2HookStartedNotification.Type;378 readonly "hook/started": CodexSchema.V2HookStartedNotification;
379 readonly "turn/completed": typeof CodexSchema.V2TurnCompletedNotification.Type;379 readonly "turn/completed": CodexSchema.V2TurnCompletedNotification;
380 readonly "hook/completed": typeof CodexSchema.V2HookCompletedNotification.Type;380 readonly "hook/completed": CodexSchema.V2HookCompletedNotification;
381 readonly "turn/diff/updated": typeof CodexSchema.V2TurnDiffUpdatedNotification.Type;381 readonly "turn/diff/updated": CodexSchema.V2TurnDiffUpdatedNotification;
382 readonly "turn/plan/updated": typeof CodexSchema.V2TurnPlanUpdatedNotification.Type;382 readonly "turn/plan/updated": CodexSchema.V2TurnPlanUpdatedNotification;
383 readonly "item/started": typeof CodexSchema.V2ItemStartedNotification.Type;383 readonly "item/started": CodexSchema.V2ItemStartedNotification;
384 readonly "item/autoApprovalReview/started": typeof CodexSchema.V2ItemGuardianApprovalReviewStartedNotification.Type;384 readonly "item/autoApprovalReview/started": CodexSchema.V2ItemGuardianApprovalReviewStartedNotification;
385 readonly "item/autoApprovalReview/completed": typeof CodexSchema.V2ItemGuardianApprovalReviewCompletedNotification.Type;385 readonly "item/autoApprovalReview/completed": CodexSchema.V2ItemGuardianApprovalReviewCompletedNotification;
386 readonly "item/completed": typeof CodexSchema.V2ItemCompletedNotification.Type;386 readonly "item/completed": CodexSchema.V2ItemCompletedNotification;
387 readonly "rawResponseItem/completed": typeof CodexSchema.V2RawResponseItemCompletedNotification.Type;387 readonly "rawResponseItem/completed": CodexSchema.V2RawResponseItemCompletedNotification;
388 readonly "item/agentMessage/delta": typeof CodexSchema.V2AgentMessageDeltaNotification.Type;388 readonly "item/agentMessage/delta": CodexSchema.V2AgentMessageDeltaNotification;
389 readonly "item/plan/delta": typeof CodexSchema.V2PlanDeltaNotification.Type;389 readonly "item/plan/delta": CodexSchema.V2PlanDeltaNotification;
390 readonly "command/exec/outputDelta": typeof CodexSchema.V2CommandExecOutputDeltaNotification.Type;390 readonly "command/exec/outputDelta": CodexSchema.V2CommandExecOutputDeltaNotification;
391 readonly "process/outputDelta": typeof CodexSchema.V2ProcessOutputDeltaNotification.Type;391 readonly "process/outputDelta": CodexSchema.V2ProcessOutputDeltaNotification;
392 readonly "process/exited": typeof CodexSchema.V2ProcessExitedNotification.Type;392 readonly "process/exited": CodexSchema.V2ProcessExitedNotification;
393 readonly "item/commandExecution/outputDelta": typeof CodexSchema.V2CommandExecutionOutputDeltaNotification.Type;393 readonly "item/commandExecution/outputDelta": CodexSchema.V2CommandExecutionOutputDeltaNotification;
394 readonly "item/commandExecution/terminalInteraction": typeof CodexSchema.V2TerminalInteractionNotification.Type;394 readonly "item/commandExecution/terminalInteraction": CodexSchema.V2TerminalInteractionNotification;
395 readonly "item/fileChange/outputDelta": typeof CodexSchema.V2FileChangeOutputDeltaNotification.Type;395 readonly "item/fileChange/outputDelta": CodexSchema.V2FileChangeOutputDeltaNotification;
396 readonly "item/fileChange/patchUpdated": typeof CodexSchema.V2FileChangePatchUpdatedNotification.Type;396 readonly "item/fileChange/patchUpdated": CodexSchema.V2FileChangePatchUpdatedNotification;
397 readonly "serverRequest/resolved": typeof CodexSchema.V2ServerRequestResolvedNotification.Type;397 readonly "serverRequest/resolved": CodexSchema.V2ServerRequestResolvedNotification;
398 readonly "item/mcpToolCall/progress": typeof CodexSchema.V2McpToolCallProgressNotification.Type;398 readonly "item/mcpToolCall/progress": CodexSchema.V2McpToolCallProgressNotification;
399 readonly "mcpServer/oauthLogin/completed": typeof CodexSchema.V2McpServerOauthLoginCompletedNotification.Type;399 readonly "mcpServer/oauthLogin/completed": CodexSchema.V2McpServerOauthLoginCompletedNotification;
400 readonly "mcpServer/startupStatus/updated": typeof CodexSchema.V2McpServerStatusUpdatedNotification.Type;400 readonly "mcpServer/startupStatus/updated": CodexSchema.V2McpServerStatusUpdatedNotification;
401 readonly "account/updated": typeof CodexSchema.V2AccountUpdatedNotification.Type;401 readonly "account/updated": CodexSchema.V2AccountUpdatedNotification;
402 readonly "account/rateLimits/updated": typeof CodexSchema.V2AccountRateLimitsUpdatedNotification.Type;402 readonly "account/rateLimits/updated": CodexSchema.V2AccountRateLimitsUpdatedNotification;
403 readonly "app/list/updated": typeof CodexSchema.V2AppListUpdatedNotification.Type;403 readonly "app/list/updated": CodexSchema.V2AppListUpdatedNotification;
404 readonly "remoteControl/status/changed": typeof CodexSchema.V2RemoteControlStatusChangedNotification.Type;404 readonly "remoteControl/status/changed": CodexSchema.V2RemoteControlStatusChangedNotification;
405 readonly "externalAgentConfig/import/completed": typeof CodexSchema.V2ExternalAgentConfigImportCompletedNotification.Type;405 readonly "externalAgentConfig/import/completed": CodexSchema.V2ExternalAgentConfigImportCompletedNotification;
406 readonly "fs/changed": typeof CodexSchema.V2FsChangedNotification.Type;406 readonly "fs/changed": CodexSchema.V2FsChangedNotification;
407 readonly "item/reasoning/summaryTextDelta": typeof CodexSchema.V2ReasoningSummaryTextDeltaNotification.Type;407 readonly "item/reasoning/summaryTextDelta": CodexSchema.V2ReasoningSummaryTextDeltaNotification;
408 readonly "item/reasoning/summaryPartAdded": typeof CodexSchema.V2ReasoningSummaryPartAddedNotification.Type;408 readonly "item/reasoning/summaryPartAdded": CodexSchema.V2ReasoningSummaryPartAddedNotification;
409 readonly "item/reasoning/textDelta": typeof CodexSchema.V2ReasoningTextDeltaNotification.Type;409 readonly "item/reasoning/textDelta": CodexSchema.V2ReasoningTextDeltaNotification;
410 readonly "thread/compacted": typeof CodexSchema.V2ContextCompactedNotification.Type;410 readonly "thread/compacted": CodexSchema.V2ContextCompactedNotification;
411 readonly "model/rerouted": typeof CodexSchema.V2ModelReroutedNotification.Type;411 readonly "model/rerouted": CodexSchema.V2ModelReroutedNotification;
412 readonly "model/verification": typeof CodexSchema.V2ModelVerificationNotification.Type;412 readonly "model/verification": CodexSchema.V2ModelVerificationNotification;
413 readonly warning: typeof CodexSchema.V2WarningNotification.Type;413 readonly warning: CodexSchema.V2WarningNotification;
414 readonly guardianWarning: typeof CodexSchema.V2GuardianWarningNotification.Type;414 readonly guardianWarning: CodexSchema.V2GuardianWarningNotification;
415 readonly deprecationNotice: typeof CodexSchema.V2DeprecationNoticeNotification.Type;415 readonly deprecationNotice: CodexSchema.V2DeprecationNoticeNotification;
416 readonly configWarning: typeof CodexSchema.V2ConfigWarningNotification.Type;416 readonly configWarning: CodexSchema.V2ConfigWarningNotification;
417 readonly "fuzzyFileSearch/sessionUpdated": typeof CodexSchema.FuzzyFileSearchSessionUpdatedNotification.Type;417 readonly "fuzzyFileSearch/sessionUpdated": CodexSchema.FuzzyFileSearchSessionUpdatedNotification;
418 readonly "fuzzyFileSearch/sessionCompleted": typeof CodexSchema.FuzzyFileSearchSessionCompletedNotification.Type;418 readonly "fuzzyFileSearch/sessionCompleted": CodexSchema.FuzzyFileSearchSessionCompletedNotification;
419 readonly "thread/realtime/started": typeof CodexSchema.V2ThreadRealtimeStartedNotification.Type;419 readonly "thread/realtime/started": CodexSchema.V2ThreadRealtimeStartedNotification;
420 readonly "thread/realtime/itemAdded": typeof CodexSchema.V2ThreadRealtimeItemAddedNotification.Type;420 readonly "thread/realtime/itemAdded": CodexSchema.V2ThreadRealtimeItemAddedNotification;
421 readonly "thread/realtime/transcript/delta": typeof CodexSchema.V2ThreadRealtimeTranscriptDeltaNotification.Type;421 readonly "thread/realtime/transcript/delta": CodexSchema.V2ThreadRealtimeTranscriptDeltaNotification;
422 readonly "thread/realtime/transcript/done": typeof CodexSchema.V2ThreadRealtimeTranscriptDoneNotification.Type;422 readonly "thread/realtime/transcript/done": CodexSchema.V2ThreadRealtimeTranscriptDoneNotification;
423 readonly "thread/realtime/outputAudio/delta": typeof CodexSchema.V2ThreadRealtimeOutputAudioDeltaNotification.Type;423 readonly "thread/realtime/outputAudio/delta": CodexSchema.V2ThreadRealtimeOutputAudioDeltaNotification;
424 readonly "thread/realtime/sdp": typeof CodexSchema.V2ThreadRealtimeSdpNotification.Type;424 readonly "thread/realtime/sdp": CodexSchema.V2ThreadRealtimeSdpNotification;
425 readonly "thread/realtime/error": typeof CodexSchema.V2ThreadRealtimeErrorNotification.Type;425 readonly "thread/realtime/error": CodexSchema.V2ThreadRealtimeErrorNotification;
426 readonly "thread/realtime/closed": typeof CodexSchema.V2ThreadRealtimeClosedNotification.Type;426 readonly "thread/realtime/closed": CodexSchema.V2ThreadRealtimeClosedNotification;
427 readonly "windows/worldWritableWarning": typeof CodexSchema.V2WindowsWorldWritableWarningNotification.Type;427 readonly "windows/worldWritableWarning": CodexSchema.V2WindowsWorldWritableWarningNotification;
428 readonly "windowsSandbox/setupCompleted": typeof CodexSchema.V2WindowsSandboxSetupCompletedNotification.Type;428 readonly "windowsSandbox/setupCompleted": CodexSchema.V2WindowsSandboxSetupCompletedNotification;
429 readonly "account/login/completed": typeof CodexSchema.V2AccountLoginCompletedNotification.Type;429 readonly "account/login/completed": CodexSchema.V2AccountLoginCompletedNotification;
430}430}
431431
432export const CLIENT_REQUEST_PARAMS = {432export const CLIENT_REQUEST_PARAMS = {
packages/effect-codex-app-server/src/client.ts+1-1
...@@ -75,7 +75,7 @@ export interface CodexAppServerClientShape {...@@ -75,7 +75,7 @@ export interface CodexAppServerClientShape {
75export class CodexAppServerClient extends Context.Service<75export class CodexAppServerClient extends Context.Service<
76 CodexAppServerClient,76 CodexAppServerClient,
77 CodexAppServerClientShape77 CodexAppServerClientShape
78>()("effect-codex-app-server/CodexAppServerClient") {}78>()("effect-codex-app-server/client/CodexAppServerClient") {}
7979
80type ServerRequestHandler = (80type ServerRequestHandler = (
81 payload: unknown,81 payload: unknown,
packages/effect-codex-app-server/tsconfig.json+3-1
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1{1{
2 "extends": "../../tsconfig.base.json",2 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},3 "compilerOptions": {
4 "types": ["node"]
5 },
4 "include": ["src", "scripts", "test"]6 "include": ["src", "scripts", "test"]
5}7}
packages/shared/package.json+1-3
...@@ -93,7 +93,7 @@...@@ -93,7 +93,7 @@
93 }93 }
94 },94 },
95 "scripts": {95 "scripts": {
96 "typecheck": "tsc --noEmit",96 "typecheck": "tsgo --noEmit",
97 "test": "vitest run"97 "test": "vitest run"
98 },98 },
99 "dependencies": {99 "dependencies": {
...@@ -101,11 +101,9 @@...@@ -101,11 +101,9 @@
101 "effect": "catalog:"101 "effect": "catalog:"
102 },102 },
103 "devDependencies": {103 "devDependencies": {
104 "@effect/language-service": "catalog:",
105 "@effect/platform-node": "catalog:",104 "@effect/platform-node": "catalog:",
106 "@effect/vitest": "catalog:",105 "@effect/vitest": "catalog:",
107 "@types/node": "catalog:",106 "@types/node": "catalog:",
108 "typescript": "catalog:",
109 "vitest": "catalog:"107 "vitest": "catalog:"
110 }108 }
111}109}
packages/shared/src/schemaJson.test.ts+21-1
...@@ -1,6 +1,9 @@...@@ -1,6 +1,9 @@
1import * as Schema from "effect/Schema";
1import { describe, expect, it } from "vitest";2import { describe, expect, it } from "vitest";
23
3import { extractJsonObject } from "./schemaJson.ts";4import { extractJsonObject, fromLenientJson } from "./schemaJson.ts";
5
6const decodeLenientJson = Schema.decodeUnknownSync(fromLenientJson(Schema.Unknown));
47
5describe("schemaJson helpers", () => {8describe("schemaJson helpers", () => {
6 it("extracts a balanced JSON object from surrounding text", () => {9 it("extracts a balanced JSON object from surrounding text", () => {
...@@ -28,4 +31,21 @@ Done.`),...@@ -28,4 +31,21 @@ Done.`),
28 it("returns trimmed input when no JSON object starts", () => {31 it("returns trimmed input when no JSON object starts", () => {
29 expect(extractJsonObject(" no structured output ")).toBe("no structured output");32 expect(extractJsonObject(" no structured output ")).toBe("no structured output");
30 });33 });
34
35 it("decodes JSON with comments and trailing commas", () => {
36 expect(
37 decodeLenientJson(`{
38 // Comments are valid in settings files.
39 "enabled": true,
40 "values": [1, 2,],
41 }`),
42 ).toEqual({
43 enabled: true,
44 values: [1, 2],
45 });
46 });
47
48 it("rejects malformed JSON after lenient preprocessing", () => {
49 expect(() => decodeLenientJson('{ "enabled": true,, }')).toThrow();
50 });
31});51});
packages/shared/src/schemaJson.ts+26-25
...@@ -45,32 +45,33 @@ export const formatSchemaError = (cause: Cause.Cause<Schema.SchemaError>) => {...@@ -45,32 +45,33 @@ export const formatSchemaError = (cause: Cause.Cause<Schema.SchemaError>) => {
45 * A `Getter` that parses a lenient JSON string (tolerating trailing commas45 * A `Getter` that parses a lenient JSON string (tolerating trailing commas
46 * and JS-style comments) into an unknown value.46 * and JS-style comments) into an unknown value.
47 *47 *
48 * Mirrors `SchemaGetter.parseJson()` but uses `parseLenientJson` instead48 * Mirrors `SchemaGetter.parseJson()` but strips JSONC syntax before parsing.
49 * of `JSON.parse`.
50 */49 */
51const parseLenientJsonGetter = SchemaGetter.onSome((input: string) =>50const decodeJsonString = Schema.decodeEffect(Schema.UnknownFromJsonString);
52 Effect.try({51
53 try: () => {52const parseLenientJsonGetter = SchemaGetter.onSome((input: string) => {
54 // Strip single-line comments — alternation preserves quoted strings.53 // Strip single-line comments - alternation preserves quoted strings.
55 let stripped = input.replace(54 let stripped = input.replace(
56 /("(?:[^"\\]|\\.)*")|\/\/[^\n]*/g,55 /("(?:[^"\\]|\\.)*")|\/\/[^\n]*/g,
57 (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""),56 (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""),
58 );57 );
5958
60 // Strip multi-line comments.59 // Strip multi-line comments.
61 stripped = stripped.replace(60 stripped = stripped.replace(
62 /("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g,61 /("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g,
63 (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""),62 (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""),
64 );63 );
6564
66 // Strip trailing commas before `}` or `]`.65 // Strip trailing commas before `}` or `]`.
67 stripped = stripped.replace(/,(\s*[}\]])/g, "$1");66 stripped = stripped.replace(/,(\s*[}\]])/g, "$1");
6867
69 return Option.some(JSON.parse(stripped));68 return decodeJsonString(stripped).pipe(
70 },69 Effect.map(Option.some),
71 catch: (e) => new SchemaIssue.InvalidValue(Option.some(input), { message: String(e) }),70 Effect.mapError(
72 }),71 (error) => new SchemaIssue.InvalidValue(Option.some(input), { message: String(error) }),
73);72 ),
73 );
74});
7475
75/**76/**
76 * Schema transformation: lenient JSONC string ↔ unknown.77 * Schema transformation: lenient JSONC string ↔ unknown.
packages/shared/tsconfig.json+3-1
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1{1{
2 "extends": "../../tsconfig.base.json",2 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},3 "compilerOptions": {
4 "types": ["node"]
5 },
4 "include": ["src"]6 "include": ["src"]
5}7}
packages/ssh/package.json+1-3
...@@ -25,7 +25,7 @@...@@ -25,7 +25,7 @@
25 }25 }
26 },26 },
27 "scripts": {27 "scripts": {
28 "typecheck": "tsc --noEmit",28 "typecheck": "tsgo --noEmit",
29 "test": "vitest run"29 "test": "vitest run"
30 },30 },
31 "dependencies": {31 "dependencies": {
...@@ -34,11 +34,9 @@...@@ -34,11 +34,9 @@
34 "effect": "catalog:"34 "effect": "catalog:"
35 },35 },
36 "devDependencies": {36 "devDependencies": {
37 "@effect/language-service": "catalog:",
38 "@effect/platform-node": "catalog:",37 "@effect/platform-node": "catalog:",
39 "@effect/vitest": "catalog:",38 "@effect/vitest": "catalog:",
40 "@types/node": "catalog:",39 "@types/node": "catalog:",
41 "typescript": "catalog:",
42 "vitest": "catalog:"40 "vitest": "catalog:"
43 }41 }
44}42}
packages/ssh/src/auth.ts+1-1
...@@ -39,7 +39,7 @@ export interface SshPasswordPromptShape {...@@ -39,7 +39,7 @@ export interface SshPasswordPromptShape {
39}39}
4040
41export class SshPasswordPrompt extends Context.Service<SshPasswordPrompt, SshPasswordPromptShape>()(41export class SshPasswordPrompt extends Context.Service<SshPasswordPrompt, SshPasswordPromptShape>()(
42 "@t3tools/ssh/SshPasswordPrompt",42 "@t3tools/ssh/auth/SshPasswordPrompt",
43) {43) {
44 static readonly disabledLayer = Layer.succeed(44 static readonly disabledLayer = Layer.succeed(
45 SshPasswordPrompt,45 SshPasswordPrompt,
packages/ssh/src/tunnel.ts+4-1
...@@ -1753,10 +1753,13 @@ const makeSshEnvironmentManager = Effect.fn("ssh/tunnel.SshEnvironmentManager.ma...@@ -1753,10 +1753,13 @@ const makeSshEnvironmentManager = Effect.fn("ssh/tunnel.SshEnvironmentManager.ma
1753 return SshEnvironmentManager.of({ ensureEnvironment, disconnectEnvironment });1753 return SshEnvironmentManager.of({ ensureEnvironment, disconnectEnvironment });
1754});1754});
17551755
1756/**
1757 * @effect-expect-leaking ChildProcessSpawner | FileSystem | HttpClient | NetService | Path | SshPasswordPrompt
1758 */
1756export class SshEnvironmentManager extends Context.Service<1759export class SshEnvironmentManager extends Context.Service<
1757 SshEnvironmentManager,1760 SshEnvironmentManager,
1758 SshEnvironmentManagerShape1761 SshEnvironmentManagerShape
1759>()("@t3tools/ssh/SshEnvironmentManager") {1762>()("@t3tools/ssh/tunnel/SshEnvironmentManager") {
1760 static readonly layer = (options: SshEnvironmentManagerOptions = {}) =>1763 static readonly layer = (options: SshEnvironmentManagerOptions = {}) =>
1761 Layer.effect(SshEnvironmentManager, makeSshEnvironmentManager(options));1764 Layer.effect(SshEnvironmentManager, makeSshEnvironmentManager(options));
1762}1765}
packages/ssh/tsconfig.json+3-1
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1{1{
2 "extends": "../../tsconfig.base.json",2 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},3 "compilerOptions": {
4 "types": ["node"]
5 },
4 "include": ["src"]6 "include": ["src"]
5}7}
packages/tailscale/package.json+1-3
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9 }9 }
10 },10 },
11 "scripts": {11 "scripts": {
12 "typecheck": "tsc --noEmit",12 "typecheck": "tsgo --noEmit",
13 "test": "vitest run"13 "test": "vitest run"
14 },14 },
15 "dependencies": {15 "dependencies": {
...@@ -17,10 +17,8 @@...@@ -17,10 +17,8 @@
17 "effect": "catalog:"17 "effect": "catalog:"
18 },18 },
19 "devDependencies": {19 "devDependencies": {
20 "@effect/language-service": "catalog:",
21 "@effect/vitest": "catalog:",20 "@effect/vitest": "catalog:",
22 "@types/node": "catalog:",21 "@types/node": "catalog:",
23 "typescript": "catalog:",
24 "vitest": "catalog:"22 "vitest": "catalog:"
25 }23 }
26}24}
packages/tailscale/tsconfig.json+3-1
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1{1{
2 "extends": "../../tsconfig.base.json",2 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},3 "compilerOptions": {
4 "types": ["node"]
5 },
4 "include": ["src"]6 "include": ["src"]
5}7}
scripts/package.json+1-3
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3 "private": true,3 "private": true,
4 "type": "module",4 "type": "module",
5 "scripts": {5 "scripts": {
6 "typecheck": "tsc --noEmit",6 "typecheck": "tsgo --noEmit",
7 "test": "vitest run"7 "test": "vitest run"
8 },8 },
9 "dependencies": {9 "dependencies": {
...@@ -14,10 +14,8 @@...@@ -14,10 +14,8 @@
14 "effect": "catalog:"14 "effect": "catalog:"
15 },15 },
16 "devDependencies": {16 "devDependencies": {
17 "@effect/language-service": "catalog:",
18 "@effect/vitest": "catalog:",17 "@effect/vitest": "catalog:",
19 "@types/bun": "catalog:",18 "@types/bun": "catalog:",
20 "typescript": "catalog:",
21 "vitest": "catalog:"19 "vitest": "catalog:"
22 }20 }
23}21}
tsconfig.base.json+4-1
...@@ -35,6 +35,7 @@...@@ -35,6 +35,7 @@
35 "globalErrorInEffectFailure": "error",35 "globalErrorInEffectFailure": "error",
36 "unknownInEffectCatch": "error",36 "unknownInEffectCatch": "error",
37 "strictBooleanExpressions": "off",37 "strictBooleanExpressions": "off",
38 "lazyEffect": "off",
38 "preferSchemaOverJson": "error",39 "preferSchemaOverJson": "error",
39 "schemaSyncInEffect": "error",40 "schemaSyncInEffect": "error",
40 "cryptoRandomUUID": "error",41 "cryptoRandomUUID": "error",
...@@ -47,7 +48,9 @@...@@ -47,7 +48,9 @@
47 "globalRandom": "error",48 "globalRandom": "error",
48 "globalRandomInEffect": "error",49 "globalRandomInEffect": "error",
49 "globalTimers": "error",50 "globalTimers": "error",
50 "globalTimersInEffect": "error"51 "globalTimersInEffect": "error",
52 "globalFetch": "error",
53 "globalFetchInEffect": "error"
51 }54 }
52 }55 }
53 ]56 ]