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 @@
1010 "dev:electron": "node scripts/dev-electron.mjs",
1111 "build": "tsdown",
1212 "start": "node scripts/start-electron.mjs",
13 "typecheck": "tsc --noEmit",
13 "typecheck": "tsgo --noEmit",
1414 "test": "vitest run --passWithNoTests",
1515 "smoke-test": "node scripts/smoke-test.mjs"
1616 },
......@@ -25,11 +25,9 @@
2525 "electron-updater": "^6.6.2"
2626 },
2727 "devDependencies": {
28 "@effect/language-service": "catalog:",
2928 "@effect/vitest": "catalog:",
3029 "@types/node": "catalog:",
3130 "tsdown": "catalog:",
32 "typescript": "catalog:",
3331 "vitest": "catalog:"
3432 },
3533 "productName": "T3 Code (Alpha)"
apps/desktop/src/app/DesktopAppIdentity.ts+1-1
......@@ -26,7 +26,7 @@ export interface DesktopAppIdentityShape {
2626export class DesktopAppIdentity extends Context.Service<
2727 DesktopAppIdentity,
2828 DesktopAppIdentityShape
29>()("t3/desktop/AppIdentity") {}
29>()("@t3tools/desktop/app/DesktopAppIdentity") {}
3030
3131const normalizeCommitHash = (value: string): Option.Option<string> => {
3232 const trimmed = value.trim();
apps/desktop/src/app/DesktopAssets.ts+1-1
......@@ -18,7 +18,7 @@ export interface DesktopAssetsShape {
1818}
1919
2020export class DesktopAssets extends Context.Service<DesktopAssets, DesktopAssetsShape>()(
21 "t3/desktop/Assets",
21 "@t3tools/desktop/app/DesktopAssets",
2222) {}
2323
2424const resolveResourcePath = Effect.fn("desktop.assets.resolveResourcePath")(function* (
apps/desktop/src/app/DesktopEnvironment.test.ts+1-3
......@@ -32,9 +32,7 @@ const makeEnvironment = (
3232 overrides: Partial<DesktopEnvironment.MakeDesktopEnvironmentInput> = {},
3333 env: Record<string, string | undefined> = {},
3434) =>
35 Effect.gen(function* () {
36 return yield* DesktopEnvironment.DesktopEnvironment;
37 }).pipe(Effect.provide(makeEnvironmentLayer(overrides, env)));
35 DesktopEnvironment.DesktopEnvironment.pipe(Effect.provide(makeEnvironmentLayer(overrides, env)));
3836
3937describe("DesktopEnvironment", () => {
4038 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 {
7878export class DesktopEnvironment extends Context.Service<
7979 DesktopEnvironment,
8080 DesktopEnvironmentShape
81>()("t3/desktop/Environment") {}
81>()("@t3tools/desktop/app/DesktopEnvironment") {}
8282
8383const APP_BASE_NAME = "T3 Code";
8484
apps/desktop/src/app/DesktopLifecycle.ts+5-2
......@@ -24,7 +24,7 @@ export interface DesktopShutdownShape {
2424}
2525
2626export class DesktopShutdown extends Context.Service<DesktopShutdown, DesktopShutdownShape>()(
27 "t3/desktop/Shutdown",
27 "@t3tools/desktop/app/DesktopLifecycle/DesktopShutdown",
2828) {}
2929
3030const makeShutdown = Effect.gen(function* () {
......@@ -61,8 +61,11 @@ export interface DesktopLifecycleShape {
6161 readonly register: Effect.Effect<void, never, Scope.Scope | DesktopLifecycleRuntimeServices>;
6262}
6363
64/**
65 * @effect-expect-leaking DesktopEnvironment | DesktopShutdown | DesktopState | DesktopWindow | ElectronApp | ElectronTheme
66 */
6467export class DesktopLifecycle extends Context.Service<DesktopLifecycle, DesktopLifecycleShape>()(
65 "t3/desktop/Lifecycle",
68 "@t3tools/desktop/app/DesktopLifecycle",
6669) {}
6770
6871const { logInfo: logLifecycleInfo, logError: logLifecycleError } =
apps/desktop/src/app/DesktopObservability.ts+1-1
......@@ -43,7 +43,7 @@ export interface DesktopBackendOutputLogShape {
4343export class DesktopBackendOutputLog extends Context.Service<
4444 DesktopBackendOutputLog,
4545 DesktopBackendOutputLogShape
46>()("t3/desktop/BackendOutputLog") {}
46>()("@t3tools/desktop/app/DesktopObservability/DesktopBackendOutputLog") {}
4747
4848const textEncoder = new TextEncoder();
4949const textDecoder = new TextDecoder();
apps/desktop/src/app/DesktopState.ts+1-1
......@@ -9,7 +9,7 @@ export interface DesktopStateShape {
99}
1010
1111export class DesktopState extends Context.Service<DesktopState, DesktopStateShape>()(
12 "t3/desktop/State",
12 "@t3tools/desktop/app/DesktopState",
1313) {}
1414
1515export const layer = Layer.effect(
apps/desktop/src/backend/DesktopBackendConfiguration.ts+1-1
......@@ -24,7 +24,7 @@ export interface DesktopBackendConfigurationShape {
2424export class DesktopBackendConfiguration extends Context.Service<
2525 DesktopBackendConfiguration,
2626 DesktopBackendConfigurationShape
27>()("t3/desktop/BackendConfiguration") {}
27>()("@t3tools/desktop/backend/DesktopBackendConfiguration") {}
2828
2929interface BackendObservabilitySettings {
3030 readonly otlpTracesUrl: Option.Option<string>;
apps/desktop/src/backend/DesktopBackendManager.ts+1-1
......@@ -116,7 +116,7 @@ export interface DesktopBackendManagerShape {
116116export class DesktopBackendManager extends Context.Service<
117117 DesktopBackendManager,
118118 DesktopBackendManagerShape
119>()("t3/desktop/BackendManager") {}
119>()("@t3tools/desktop/backend/DesktopBackendManager") {}
120120
121121const { logWarning: logBackendManagerWarning, logError: logBackendManagerError } =
122122 DesktopObservability.makeComponentLogger("desktop-backend-manager");
apps/desktop/src/backend/DesktopServerExposure.ts+2-2
......@@ -275,7 +275,7 @@ export interface DesktopServerExposureShape {
275275export class DesktopServerExposure extends Context.Service<
276276 DesktopServerExposure,
277277 DesktopServerExposureShape
278>()("t3/desktop/ServerExposure") {}
278>()("@t3tools/desktop/backend/DesktopServerExposure") {}
279279
280280export interface DesktopNetworkInterfacesServiceShape {
281281 readonly read: Effect.Effect<DesktopNetworkInterfaces>;
......@@ -284,7 +284,7 @@ export interface DesktopNetworkInterfacesServiceShape {
284284export class DesktopNetworkInterfacesService extends Context.Service<
285285 DesktopNetworkInterfacesService,
286286 DesktopNetworkInterfacesServiceShape
287>()("t3/desktop/ServerExposure/NetworkInterfaces") {}
287>()("@t3tools/desktop/backend/DesktopServerExposure/DesktopNetworkInterfacesService") {}
288288
289289interface RuntimeState {
290290 readonly requestedMode: DesktopServerExposureMode;
apps/desktop/src/electron/ElectronApp.ts+1-1
......@@ -39,7 +39,7 @@ export interface ElectronAppShape {
3939}
4040
4141export class ElectronApp extends Context.Service<ElectronApp, ElectronAppShape>()(
42 "t3/desktop/electron/App",
42 "@t3tools/desktop/electron/ElectronApp",
4343) {}
4444
4545const addScopedAppListener = <Args extends ReadonlyArray<unknown>>(
apps/desktop/src/electron/ElectronDialog.ts+1-1
......@@ -29,7 +29,7 @@ export interface ElectronDialogShape {
2929}
3030
3131export class ElectronDialog extends Context.Service<ElectronDialog, ElectronDialogShape>()(
32 "t3/desktop/electron/Dialog",
32 "@t3tools/desktop/electron/ElectronDialog",
3333) {}
3434
3535const make = ElectronDialog.of({
apps/desktop/src/electron/ElectronMenu.ts+1-1
......@@ -33,7 +33,7 @@ export interface ElectronMenuShape {
3333}
3434
3535export class ElectronMenu extends Context.Service<ElectronMenu, ElectronMenuShape>()(
36 "t3/desktop/electron/Menu",
36 "@t3tools/desktop/electron/ElectronMenu",
3737) {}
3838
3939function normalizeContextMenuItems(source: readonly ContextMenuItem[]): ContextMenuItem[] {
apps/desktop/src/electron/ElectronProtocol.ts+1-1
......@@ -52,7 +52,7 @@ export interface ElectronProtocolShape {
5252}
5353
5454export class ElectronProtocol extends Context.Service<ElectronProtocol, ElectronProtocolShape>()(
55 "t3/desktop/electron/Protocol",
55 "@t3tools/desktop/electron/ElectronProtocol",
5656) {}
5757
5858export function normalizeDesktopProtocolPathname(rawPath: string): Option.Option<string> {
apps/desktop/src/electron/ElectronSafeStorage.ts+1-1
......@@ -48,7 +48,7 @@ export interface ElectronSafeStorageShape {
4848export class ElectronSafeStorage extends Context.Service<
4949 ElectronSafeStorage,
5050 ElectronSafeStorageShape
51>()("@t3tools/desktop/ElectronSafeStorage") {}
51>()("@t3tools/desktop/electron/ElectronSafeStorage") {}
5252
5353const make = ElectronSafeStorage.of({
5454 isEncryptionAvailable: Effect.try({
apps/desktop/src/electron/ElectronShell.ts+1-1
......@@ -26,7 +26,7 @@ export interface ElectronShellShape {
2626}
2727
2828export class ElectronShell extends Context.Service<ElectronShell, ElectronShellShape>()(
29 "t3/desktop/electron/Shell",
29 "@t3tools/desktop/electron/ElectronShell",
3030) {}
3131
3232const make = ElectronShell.of({
apps/desktop/src/electron/ElectronTheme.ts+1-1
......@@ -13,7 +13,7 @@ export interface ElectronThemeShape {
1313}
1414
1515export class ElectronTheme extends Context.Service<ElectronTheme, ElectronThemeShape>()(
16 "t3/desktop/electron/Theme",
16 "@t3tools/desktop/electron/ElectronTheme",
1717) {}
1818
1919const make = ElectronTheme.of({
apps/desktop/src/electron/ElectronUpdater.ts+1-1
......@@ -67,7 +67,7 @@ export interface ElectronUpdaterShape {
6767}
6868
6969export class ElectronUpdater extends Context.Service<ElectronUpdater, ElectronUpdaterShape>()(
70 "t3/desktop/electron/Updater",
70 "@t3tools/desktop/electron/ElectronUpdater",
7171) {}
7272
7373export const layer = Layer.succeed(ElectronUpdater, {
apps/desktop/src/electron/ElectronWindow.ts+1-1
......@@ -33,7 +33,7 @@ export interface ElectronWindowShape {
3333}
3434
3535export class ElectronWindow extends Context.Service<ElectronWindow, ElectronWindowShape>()(
36 "t3/desktop/electron/Window",
36 "@t3tools/desktop/electron/ElectronWindow",
3737) {}
3838
3939const make = Effect.gen(function* () {
apps/desktop/src/ipc/DesktopIpc.ts+3-1
......@@ -42,7 +42,9 @@ export interface DesktopIpcShape {
4242 ) => Effect.Effect<void, never, R | Scope.Scope>;
4343}
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
4749export const make = (ipcMain: DesktopIpcMain): DesktopIpcShape =>
4850 DesktopIpc.of({
apps/desktop/src/settings/DesktopAppSettings.ts+1-1
......@@ -89,7 +89,7 @@ export interface DesktopAppSettingsShape {
8989export class DesktopAppSettings extends Context.Service<
9090 DesktopAppSettings,
9191 DesktopAppSettingsShape
92>()("t3/desktop/AppSettings") {}
92>()("@t3tools/desktop/settings/DesktopAppSettings") {}
9393
9494export function resolveDefaultDesktopSettings(appVersion: string): DesktopSettings {
9595 return {
apps/desktop/src/settings/DesktopClientSettings.ts+1-1
......@@ -49,7 +49,7 @@ export interface DesktopClientSettingsShape {
4949export class DesktopClientSettings extends Context.Service<
5050 DesktopClientSettings,
5151 DesktopClientSettingsShape
52>()("t3/desktop/ClientSettings") {}
52>()("@t3tools/desktop/settings/DesktopClientSettings") {}
5353
5454const readClientSettings = (
5555 fileSystem: FileSystem.FileSystem,
apps/desktop/src/settings/DesktopSavedEnvironments.ts+1-1
......@@ -121,7 +121,7 @@ export interface DesktopSavedEnvironmentsShape {
121121export class DesktopSavedEnvironments extends Context.Service<
122122 DesktopSavedEnvironments,
123123 DesktopSavedEnvironmentsShape
124>()("t3/desktop/SavedEnvironments") {}
124>()("@t3tools/desktop/settings/DesktopSavedEnvironments") {}
125125
126126function toPersistedSavedEnvironmentRecord(
127127 record: PersistedSavedEnvironmentStorageRecord,
apps/desktop/src/shell/DesktopShellEnvironment.ts+1-1
......@@ -26,7 +26,7 @@ export interface DesktopShellEnvironmentShape {
2626export class DesktopShellEnvironment extends Context.Service<
2727 DesktopShellEnvironment,
2828 DesktopShellEnvironmentShape
29>()("t3/desktop/ShellEnvironment") {}
29>()("@t3tools/desktop/shell/DesktopShellEnvironment") {}
3030
3131const LOGIN_SHELL_ENV_NAMES = [
3232 "PATH",
apps/desktop/src/ssh/DesktopSshEnvironment.ts+1-1
......@@ -68,7 +68,7 @@ export interface DesktopSshEnvironmentShape {
6868export class DesktopSshEnvironment extends Context.Service<
6969 DesktopSshEnvironment,
7070 DesktopSshEnvironmentShape
71>()("t3/desktop/SshEnvironment") {}
71>()("@t3tools/desktop/ssh/DesktopSshEnvironment") {}
7272
7373export interface DesktopSshEnvironmentLayerOptions {
7474 readonly resolveCliPackageSpec?: () => string;
apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts+1-1
......@@ -129,7 +129,7 @@ export interface DesktopSshPasswordPromptsShape {
129129export class DesktopSshPasswordPrompts extends Context.Service<
130130 DesktopSshPasswordPrompts,
131131 DesktopSshPasswordPromptsShape
132>()("t3/desktop/SshPasswordPrompts") {}
132>()("@t3tools/desktop/ssh/DesktopSshPasswordPrompts") {}
133133
134134interface PendingSshPasswordPrompt {
135135 readonly requestId: string;
apps/desktop/src/ssh/DesktopSshRemoteApi.ts+1-1
......@@ -53,7 +53,7 @@ export interface DesktopSshRemoteApiShape {
5353export class DesktopSshRemoteApi extends Context.Service<
5454 DesktopSshRemoteApi,
5555 DesktopSshRemoteApiShape
56>()("t3/desktop/SshRemoteApi") {}
56>()("@t3tools/desktop/ssh/DesktopSshRemoteApi") {}
5757
5858const decodeExecutionEnvironmentDescriptor = Schema.decodeUnknownEffect(
5959 ExecutionEnvironmentDescriptor,
apps/desktop/src/updates/DesktopUpdates.ts+1-1
......@@ -100,7 +100,7 @@ export interface DesktopUpdatesShape {
100100}
101101
102102export class DesktopUpdates extends Context.Service<DesktopUpdates, DesktopUpdatesShape>()(
103 "t3/desktop/Updates",
103 "@t3tools/desktop/updates/DesktopUpdates",
104104) {}
105105
106106const {
apps/desktop/src/window/DesktopApplicationMenu.ts+1-1
......@@ -21,7 +21,7 @@ export interface DesktopApplicationMenuShape {
2121export class DesktopApplicationMenu extends Context.Service<
2222 DesktopApplicationMenu,
2323 DesktopApplicationMenuShape
24>()("t3/desktop/ApplicationMenu") {}
24>()("@t3tools/desktop/window/DesktopApplicationMenu") {}
2525
2626type DesktopApplicationMenuRuntimeServices =
2727 | DesktopUpdates.DesktopUpdates
apps/desktop/src/window/DesktopWindow.ts+1-1
......@@ -62,7 +62,7 @@ export interface DesktopWindowShape {
6262}
6363
6464export class DesktopWindow extends Context.Service<DesktopWindow, DesktopWindowShape>()(
65 "t3/desktop/Window",
65 "@t3tools/desktop/window/DesktopWindow",
6666) {}
6767
6868const { logInfo: logWindowInfo, logWarning: logWindowWarning } =
apps/server/package.json+1-3
......@@ -19,7 +19,7 @@
1919 "build": "node scripts/cli.ts build",
2020 "build:bundle": "tsdown",
2121 "start": "node dist/bin.mjs",
22 "typecheck": "tsc --noEmit",
22 "typecheck": "tsgo --noEmit",
2323 "test": "vitest run"
2424 },
2525 "dependencies": {
......@@ -34,7 +34,6 @@
3434 "node-pty": "^1.1.0"
3535 },
3636 "devDependencies": {
37 "@effect/language-service": "catalog:",
3837 "@effect/vitest": "catalog:",
3938 "@t3tools/contracts": "workspace:*",
4039 "@t3tools/shared": "workspace:*",
......@@ -45,7 +44,6 @@
4544 "effect-acp": "workspace:*",
4645 "effect-codex-app-server": "workspace:*",
4746 "tsdown": "catalog:",
48 "typescript": "catalog:",
4947 "vitest": "catalog:"
5048 },
5149 "engines": {
apps/server/src/auth/Layers/BootstrapCredentialService.ts+3-1
......@@ -1,4 +1,5 @@
11import type { AuthPairingLink } from "@t3tools/contracts";
2import * as Crypto from "effect/Crypto";
23import * as DateTime from "effect/DateTime";
34import * as Duration from "effect/Duration";
45import * as Effect from "effect/Effect";
......@@ -46,6 +47,7 @@ const generatePairingToken = (): string => {
4647};
4748
4849export const makeBootstrapCredentialService = Effect.gen(function* () {
50 const crypto = yield* Crypto.Crypto;
4951 const config = yield* ServerConfig;
5052 const pairingLinks = yield* AuthPairingLinkRepository;
5153 const seededGrantsRef = yield* Ref.make(new Map<string, StoredBootstrapGrant>());
......@@ -141,7 +143,7 @@ export const makeBootstrapCredentialService = Effect.gen(function* () {
141143
142144 const issueOneTimeToken: BootstrapCredentialServiceShape["issueOneTimeToken"] = (input) =>
143145 Effect.gen(function* () {
144 const id = crypto.randomUUID();
146 const id = yield* crypto.randomUUIDv4;
145147 const credential = generatePairingToken();
146148 const ttl = input?.ttl ?? DEFAULT_ONE_TIME_TOKEN_TTL_MINUTES;
147149 const now = yield* DateTime.now;
apps/server/src/auth/Layers/SessionCredentialService.ts+3-1
......@@ -1,5 +1,6 @@
11import { AuthSessionId, type AuthClientMetadata, type AuthClientSession } from "@t3tools/contracts";
22import * as Clock from "effect/Clock";
3import * as Crypto from "effect/Crypto";
34import * as DateTime from "effect/DateTime";
45import * as Duration from "effect/Duration";
56import * as Effect from "effect/Effect";
......@@ -90,6 +91,7 @@ function toAuthClientSession(input: Omit<AuthClientSession, "current">): AuthCli
9091}
9192
9293export const makeSessionCredentialService = Effect.gen(function* () {
94 const crypto = yield* Crypto.Crypto;
9395 const serverConfig = yield* ServerConfig;
9496 const secretStore = yield* ServerSecretStore;
9597 const authSessions = yield* AuthSessionRepository;
......@@ -203,7 +205,7 @@ export const makeSessionCredentialService = Effect.gen(function* () {
203205 const encodeClaims = Schema.encodeEffect(Schema.fromJsonString(SessionClaims));
204206 const issue: SessionCredentialServiceShape["issue"] = (input) =>
205207 Effect.gen(function* () {
206 const sessionId = AuthSessionId.make(crypto.randomUUID());
208 const sessionId = AuthSessionId.make(yield* crypto.randomUUIDv4);
207209 const issuedAt = yield* DateTime.now;
208210 const expiresAt = DateTime.add(issuedAt, {
209211 milliseconds: Duration.toMillis(input?.ttl ?? DEFAULT_SESSION_TTL),
apps/server/src/auth/Services/AuthControlPlane.ts+1-1
......@@ -69,5 +69,5 @@ export interface AuthControlPlaneShape {
6969}
7070
7171export class AuthControlPlane extends Context.Service<AuthControlPlane, AuthControlPlaneShape>()(
72 "t3/AuthControlPlane",
72 "t3/auth/Services/AuthControlPlane",
7373) {}
apps/server/src/bin.test.ts+1-1
......@@ -1,4 +1,4 @@
1// @effect-diagnostics-next-line nodeBuiltinImport:off - NodeHttpServer.layer takes `NodeHttp.createServer` as arg
1// @effect-diagnostics nodeBuiltinImport:off - CLI integration exercises Node HTTP and filesystem boundaries.
22import * as NodeHttp from "node:http";
33import { mkdtempSync } from "node:fs";
44import { tmpdir } from "node:os";
apps/server/src/orchestration/Layers/CheckpointReactor.ts+63-41
......@@ -9,10 +9,12 @@ import {
99 type ProviderRuntimeEvent,
1010} from "@t3tools/contracts";
1111import * as Cause from "effect/Cause";
12import * as Crypto from "effect/Crypto";
1213import * as DateTime from "effect/DateTime";
1314import * as Effect from "effect/Effect";
1415import * as Layer from "effect/Layer";
1516import * as Option from "effect/Option";
17import type * as PlatformError from "effect/PlatformError";
1618import * as Stream from "effect/Stream";
1719import { makeDrainableWorker } from "@t3tools/shared/DrainableWorker";
1820
......@@ -69,10 +71,12 @@ function checkpointStatusFromRuntime(status: string | undefined): "ready" | "mis
6971 }
7072}
7173
72const serverCommandId = (tag: string): CommandId =>
73 CommandId.make(`server:${tag}:${crypto.randomUUID()}`);
74
7574const 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}`)));
7680 const orchestrationEngine = yield* OrchestrationEngineService;
7781 const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
7882 const providerService = yield* ProviderService;
......@@ -87,24 +91,31 @@ const make = Effect.gen(function* () {
8791 readonly detail: string;
8892 readonly createdAt: string;
8993 }) =>
90 orchestrationEngine.dispatch({
91 type: "thread.activity.append",
94 Effect.all({
9295 commandId: serverCommandId("checkpoint-revert-failure"),
93 threadId: input.threadId,
94 activity: {
95 id: EventId.make(crypto.randomUUID()),
96 tone: "error",
97 kind: "checkpoint.revert.failed",
98 summary: "Checkpoint revert failed",
99 payload: {
100 turnCount: input.turnCount,
101 detail: input.detail,
102 },
103 turnId: null,
104 createdAt: input.createdAt,
105 },
106 createdAt: input.createdAt,
107 });
96 activityId: serverEventId,
97 }).pipe(
98 Effect.flatMap(({ commandId, activityId }) =>
99 orchestrationEngine.dispatch({
100 type: "thread.activity.append",
101 commandId,
102 threadId: input.threadId,
103 activity: {
104 id: activityId,
105 tone: "error",
106 kind: "checkpoint.revert.failed",
107 summary: "Checkpoint revert failed",
108 payload: {
109 turnCount: input.turnCount,
110 detail: input.detail,
111 },
112 turnId: null,
113 createdAt: input.createdAt,
114 },
115 createdAt: input.createdAt,
116 }),
117 ),
118 );
108119
109120 const appendCaptureFailureActivity = (input: {
110121 readonly threadId: ThreadId;
......@@ -112,23 +123,30 @@ const make = Effect.gen(function* () {
112123 readonly detail: string;
113124 readonly createdAt: string;
114125 }) =>
115 orchestrationEngine.dispatch({
116 type: "thread.activity.append",
126 Effect.all({
117127 commandId: serverCommandId("checkpoint-capture-failure"),
118 threadId: input.threadId,
119 activity: {
120 id: EventId.make(crypto.randomUUID()),
121 tone: "error",
122 kind: "checkpoint.capture.failed",
123 summary: "Checkpoint capture failed",
124 payload: {
125 detail: input.detail,
126 },
127 turnId: input.turnId,
128 createdAt: input.createdAt,
129 },
130 createdAt: input.createdAt,
131 });
128 activityId: serverEventId,
129 }).pipe(
130 Effect.flatMap(({ commandId, activityId }) =>
131 orchestrationEngine.dispatch({
132 type: "thread.activity.append",
133 commandId,
134 threadId: input.threadId,
135 activity: {
136 id: activityId,
137 tone: "error",
138 kind: "checkpoint.capture.failed",
139 summary: "Checkpoint capture failed",
140 payload: {
141 detail: input.detail,
142 },
143 turnId: input.turnId,
144 createdAt: input.createdAt,
145 },
146 createdAt: input.createdAt,
147 }),
148 ),
149 );
132150
133151 const resolveSessionRuntimeForThread = Effect.fn("resolveSessionRuntimeForThread")(function* (
134152 threadId: ThreadId,
......@@ -281,7 +299,7 @@ const make = Effect.gen(function* () {
281299
282300 yield* orchestrationEngine.dispatch({
283301 type: "thread.turn.diff.complete",
284 commandId: serverCommandId("checkpoint-turn-diff-complete"),
302 commandId: yield* serverCommandId("checkpoint-turn-diff-complete"),
285303 threadId: input.threadId,
286304 turnId: input.turnId,
287305 completedAt: input.createdAt,
......@@ -311,10 +329,10 @@ const make = Effect.gen(function* () {
311329
312330 yield* orchestrationEngine.dispatch({
313331 type: "thread.activity.append",
314 commandId: serverCommandId("checkpoint-captured-activity"),
332 commandId: yield* serverCommandId("checkpoint-captured-activity"),
315333 threadId: input.threadId,
316334 activity: {
317 id: EventId.make(crypto.randomUUID()),
335 id: EventId.make(yield* randomUUID),
318336 tone: "info",
319337 kind: "checkpoint.captured",
320338 summary: "Checkpoint captured",
......@@ -697,7 +715,7 @@ const make = Effect.gen(function* () {
697715 yield* orchestrationEngine
698716 .dispatch({
699717 type: "thread.revert.complete",
700 commandId: serverCommandId("checkpoint-revert-complete"),
718 commandId: yield* serverCommandId("checkpoint-revert-complete"),
701719 threadId: event.payload.threadId,
702720 turnCount: event.payload.turnCount,
703721 createdAt: now,
......@@ -787,7 +805,11 @@ const make = Effect.gen(function* () {
787805
788806 const processInput = (
789807 input: ReactorInput,
790 ): Effect.Effect<void, CheckpointStoreError | OrchestrationDispatchError, never> =>
808 ): Effect.Effect<
809 void,
810 CheckpointStoreError | OrchestrationDispatchError | PlatformError.PlatformError,
811 never
812 > =>
791813 input.source === "domain" ? processDomainEvent(input.event) : processRuntimeEvent(input.event);
792814
793815 const processInputSafely = (input: ReactorInput) =>
apps/server/src/orchestration/http.ts+4-2
......@@ -58,8 +58,10 @@ export const orchestrationSnapshotRouteLayer = HttpRouter.add(
5858 status: 200,
5959 });
6060 }).pipe(
61 Effect.catchTag("OrchestrationDispatchCommandError", respondToOrchestrationHttpError),
62 Effect.catchTag("OrchestrationGetSnapshotError", respondToOrchestrationHttpError),
61 Effect.catchTags({
62 OrchestrationDispatchCommandError: respondToOrchestrationHttpError,
63 OrchestrationGetSnapshotError: respondToOrchestrationHttpError,
64 }),
6365 ),
6466);
6567
apps/server/src/persistence/Layers/AuthSessions.ts+1-1
......@@ -40,7 +40,7 @@ const AuthSessionDbRow = Schema.Struct({
4040 revokedAt: Schema.NullOr(Schema.DateTimeUtcFromString),
4141});
4242
43function toAuthSessionRecord(row: typeof AuthSessionDbRow.Type): typeof AuthSessionRecord.Type {
43function toAuthSessionRecord(row: typeof AuthSessionDbRow.Type): AuthSessionRecord {
4444 return {
4545 sessionId: row.sessionId,
4646 subject: row.subject,
apps/server/src/persistence/Migrations/009_ProviderSessionRuntimeMode.ts+1-3
......@@ -1,6 +1,4 @@
11import * as SqlClient from "effect/unstable/sql/SqlClient";
22import * as Effect from "effect/Effect";
33
4export default Effect.gen(function* () {
5 yield* SqlClient.SqlClient;
6});
4export default Effect.asVoid(SqlClient.SqlClient);
apps/server/src/process/externalLauncher.ts+1-1
......@@ -257,7 +257,7 @@ export interface ExternalLauncherShape {
257257 * ExternalLauncher - Service tag for browser/editor launch operations.
258258 */
259259export class ExternalLauncher extends Context.Service<ExternalLauncher, ExternalLauncherShape>()(
260 "t3/process/ExternalLauncher",
260 "t3/process/externalLauncher",
261261) {}
262262
263263// ==============================
apps/server/src/processRunner.ts+1-1
......@@ -90,7 +90,7 @@ export interface ProcessRunnerShape {
9090}
9191
9292export class ProcessRunner extends Context.Service<ProcessRunner, ProcessRunnerShape>()(
93 "t3/process/ProcessRunner",
93 "t3/processRunner",
9494) {}
9595
9696const DEFAULT_TIMEOUT = "60 seconds";
apps/server/src/project/Services/ProjectSetupScriptRunner.ts+1-1
......@@ -41,4 +41,4 @@ export interface ProjectSetupScriptRunnerShape {
4141export class ProjectSetupScriptRunner extends Context.Service<
4242 ProjectSetupScriptRunner,
4343 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);
4242
4343// Test-local service tag so the rest of the file can keep using `yield* ClaudeAdapter`.
4444class ClaudeAdapter extends Context.Service<ClaudeAdapter, ClaudeAdapterShape>()(
45 "test/ClaudeAdapter",
45 "t3/provider/Layers/ClaudeAdapter.test/ClaudeAdapter",
4646) {}
4747
4848class FakeClaudeQuery implements AsyncIterable<SDKMessage> {
apps/server/src/provider/Layers/CodexAdapter.test.ts+1-1
......@@ -50,7 +50,7 @@ const decodeCodexSettings = Schema.decodeSync(CodexSettings);
5050
5151// Test-local service tag so the rest of the file can keep using `yield* CodexAdapter`.
5252class CodexAdapter extends Context.Service<CodexAdapter, CodexAdapterShape>()(
53 "test/CodexAdapter",
53 "t3/provider/Layers/CodexAdapter.test/CodexAdapter",
5454) {}
5555
5656const 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);
3232
3333// Test-local service tag so the rest of the file can keep using `yield* CursorAdapter`.
3434class CursorAdapter extends Context.Service<CursorAdapter, CursorAdapterShape>()(
35 "test/CursorAdapter",
35 "t3/provider/Layers/CursorAdapter.test/CursorAdapter",
3636) {}
3737
3838const __dirname = path.dirname(fileURLToPath(import.meta.url));
apps/server/src/provider/Layers/CursorAdapter.ts+1-1
......@@ -97,7 +97,7 @@ export interface CursorAdapterLiveOptions {
9797 * Selections are honored when `modelSelection.instanceId` matches this value.
9898 * Defaults to the legacy built-in instance id (`cursor`).
9999 */
100 readonly instanceId?: typeof ProviderInstanceId.Type;
100 readonly instanceId?: ProviderInstanceId;
101101 /**
102102 * Optional per-session settings resolver. When provided the adapter yields
103103 * 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";
1414import * as Effect from "effect/Effect";
1515import * as Exit from "effect/Exit";
1616import * as Logger from "effect/Logger";
17import * as Schema from "effect/Schema";
1718import * as Scope from "effect/Scope";
1819import * as SynchronizedRef from "effect/SynchronizedRef";
1920
......@@ -24,6 +25,7 @@ const DEFAULT_MAX_FILES = 10;
2425const DEFAULT_BATCH_WINDOW_MS = 200;
2526const GLOBAL_THREAD_SEGMENT = "_global";
2627const LOG_SCOPE = "provider-observability";
28const encodeUnknownJsonString = Schema.encodeUnknownEffect(Schema.UnknownFromJsonString);
2729
2830export type EventNdjsonStream = "native" | "canonical" | "orchestration";
2931
......@@ -87,26 +89,13 @@ function resolveStreamLabel(stream: EventNdjsonStream): string {
8789const toLogMessage = Effect.fn("toLogMessage")(function* (
8890 event: unknown,
8991): Effect.fn.Return<string | undefined> {
90 const serialized = yield* Effect.sync(() => {
91 try {
92 return { ok: true as const, value: JSON.stringify(event) };
93 } catch (error) {
94 return { ok: false as const, error };
95 }
96 });
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;
92 return yield* encodeUnknownJsonString(event).pipe(
93 Effect.catch((error) =>
94 logWarning("failed to serialize provider event log record", { error }).pipe(
95 Effect.as(undefined),
96 ),
97 ),
98 );
11099});
111100
112101const makeThreadWriter = Effect.fn("makeThreadWriter")(function* (input: {
apps/server/src/provider/Layers/OpenCodeAdapter.test.ts+1-1
......@@ -37,7 +37,7 @@ import {
3737
3838// Test-local service tag so the rest of the file can keep using `yield* OpenCodeAdapter`.
3939class OpenCodeAdapter extends Context.Service<OpenCodeAdapter, OpenCodeAdapterShape>()(
40 "test/OpenCodeAdapter",
40 "t3/provider/Layers/OpenCodeAdapter.test/OpenCodeAdapter",
4141) {}
4242
4343const 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
408408 const inventoryExit = yield* Effect.exit(
409409 Effect.scoped(
410410 Effect.gen(function* () {
411 const server = yield* openCodeRuntime
412 .connectToOpenCodeServer({
413 binaryPath: openCodeSettings.binaryPath,
414 serverUrl: openCodeSettings.serverUrl,
415 environment,
416 })
417 .pipe(
418 Effect.mapError(
419 (cause) =>
420 new OpenCodeProbeError({ cause, detail: openCodeRuntimeErrorDetail(cause) }),
421 ),
422 );
423 return yield* openCodeRuntime
424 .loadOpenCodeInventory(
425 openCodeRuntime.createOpenCodeSdkClient({
426 baseUrl: server.url,
427 directory: cwd,
428 ...(isExternalServer && openCodeSettings.serverPassword
429 ? { serverPassword: openCodeSettings.serverPassword }
430 : {}),
431 }),
432 )
433 .pipe(
434 Effect.mapError(
435 (cause) =>
436 new OpenCodeProbeError({ cause, detail: openCodeRuntimeErrorDetail(cause) }),
437 ),
438 );
439 }),
411 const server = yield* openCodeRuntime.connectToOpenCodeServer({
412 binaryPath: openCodeSettings.binaryPath,
413 serverUrl: openCodeSettings.serverUrl,
414 environment,
415 });
416 return yield* openCodeRuntime.loadOpenCodeInventory(
417 openCodeRuntime.createOpenCodeSdkClient({
418 baseUrl: server.url,
419 directory: cwd,
420 ...(isExternalServer && openCodeSettings.serverPassword
421 ? { serverPassword: openCodeSettings.serverPassword }
422 : {}),
423 }),
424 );
425 }).pipe(
426 Effect.mapError(
427 (cause) => new OpenCodeProbeError({ cause, detail: openCodeRuntimeErrorDetail(cause) }),
428 ),
429 ),
440430 ),
441431 );
442432 if (inventoryExit._tag === "Failure") {
apps/server/src/provider/Layers/ProviderEventLoggers.ts+1-1
......@@ -50,7 +50,7 @@ export interface ProviderEventLoggersShape {
5050export class ProviderEventLoggers extends Context.Service<
5151 ProviderEventLoggers,
5252 ProviderEventLoggersShape
53>()("t3/provider/ProviderEventLoggers") {}
53>()("t3/provider/Layers/ProviderEventLoggers") {}
5454
5555/**
5656 * 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", () =>
346346 const scope = yield* Scope.make();
347347 const runtimeServices = yield* Layer.build(providerLayer).pipe(Scope.provide(scope));
348348
349 yield* Effect.gen(function* () {
350 yield* ProviderService;
351 }).pipe(Effect.provide(runtimeServices));
349 yield* ProviderService.pipe(Effect.provide(runtimeServices));
352350 const closeExit = yield* Scope.close(scope, Exit.void).pipe(Effect.exit);
353351
354352 assert.equal(Exit.isSuccess(closeExit), true);
......@@ -636,9 +634,7 @@ it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", (
636634 Layer.provide(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)),
637635 );
638636
639 yield* Effect.gen(function* () {
640 yield* ProviderService;
641 }).pipe(Effect.provide(providerLayer));
637 yield* ProviderService.pipe(Effect.provide(providerLayer));
642638
643639 const persistedProvider = yield* Effect.gen(function* () {
644640 const directory = yield* ProviderSessionDirectory;
apps/server/src/provider/opencodeRuntime.ts+1-1
......@@ -544,7 +544,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () {
544544});
545545
546546export class OpenCodeRuntime extends Context.Service<OpenCodeRuntime, OpenCodeRuntimeShape>()(
547 "t3/provider/OpenCodeRuntime",
547 "t3/provider/opencodeRuntime",
548548) {}
549549
550550export const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(
apps/server/src/provider/providerMaintenanceRunner.ts+1-1
......@@ -53,7 +53,7 @@ export interface ProviderMaintenanceRunnerShape {
5353export class ProviderMaintenanceRunner extends Context.Service<
5454 ProviderMaintenanceRunner,
5555 ProviderMaintenanceRunnerShape
56>()("t3/provider/ProviderMaintenanceRunner") {}
56>()("t3/provider/providerMaintenanceRunner") {}
5757
5858class ProviderMaintenanceCommandError extends Data.TaggedError("ProviderMaintenanceCommandError")<{
5959 readonly message: string;
apps/server/src/server.test.ts+126-221
......@@ -40,6 +40,7 @@ import * as Path from "effect/Path";
4040import * as Stream from "effect/Stream";
4141import { ChildProcessSpawner } from "effect/unstable/process";
4242import {
43 Cookies,
4344 FetchHttpClient,
4445 HttpBody,
4546 HttpClient,
......@@ -780,13 +781,6 @@ const appendSessionCookieToWsUrl = (url: string, sessionCookieHeader: string) =>
780781 return isAbsoluteUrl ? next.toString() : `${next.pathname}${next.search}${next.hash}`;
781782};
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
790784const bootstrapBrowserSession = (
791785 credential = defaultDesktopBootstrapToken,
792786 options?: {
......@@ -794,20 +788,11 @@ const bootstrapBrowserSession = (
794788 },
795789) =>
796790 Effect.gen(function* () {
797 const bootstrapUrl = yield* getHttpServerUrl("/api/auth/bootstrap");
798 const response = yield* Effect.promise(() =>
799 fetch(bootstrapUrl, {
800 method: "POST",
801 headers: {
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 {
791 const response = yield* HttpClient.post("/api/auth/bootstrap", {
792 headers: options?.headers,
793 body: yield* HttpBody.json({ credential }),
794 });
795 const body = (yield* response.json) as {
811796 readonly authenticated: boolean;
812797 readonly sessionMethod: string;
813798 readonly expiresAt: string;
......@@ -815,7 +800,7 @@ const bootstrapBrowserSession = (
815800 return {
816801 response,
817802 body,
818 cookie: response.headers.get("set-cookie"),
803 cookie: Cookies.toSetCookieHeaders(response.cookies)[0] ?? null,
819804 };
820805 });
821806
......@@ -826,20 +811,11 @@ const bootstrapBearerSession = (
826811 },
827812) =>
828813 Effect.gen(function* () {
829 const bootstrapUrl = yield* getHttpServerUrl("/api/auth/bootstrap/bearer");
830 const response = yield* Effect.promise(() =>
831 fetch(bootstrapUrl, {
832 method: "POST",
833 headers: {
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 {
814 const response = yield* HttpClient.post("/api/auth/bootstrap/bearer", {
815 headers: options?.headers,
816 body: yield* HttpBody.json({ credential }),
817 });
818 const body = (yield* response.json) as {
843819 readonly authenticated: boolean;
844820 readonly sessionMethod: string;
845821 readonly expiresAt: string;
......@@ -859,7 +835,7 @@ class AuthenticationGetterError extends Data.TaggedError("AuthenticationGetterEr
859835const getAuthenticatedSessionCookieHeader = (credential = defaultDesktopBootstrapToken) =>
860836 Effect.gen(function* () {
861837 const { response, cookie } = yield* bootstrapBrowserSession(credential);
862 if (!response.ok) {
838 if (response.status !== 200) {
863839 return yield* new AuthenticationGetterError({
864840 message: `Expected bootstrap session response to succeed, got ${response.status}`,
865841 });
......@@ -877,7 +853,7 @@ const getAuthenticatedSessionCookieHeader = (credential = defaultDesktopBootstra
877853const getAuthenticatedBearerSessionToken = (credential = defaultDesktopBootstrapToken) =>
878854 Effect.gen(function* () {
879855 const { response, body } = yield* bootstrapBearerSession(credential);
880 if (!response.ok) {
856 if (response.status !== 200) {
881857 return yield* new AuthenticationGetterError({
882858 message: `Expected bearer bootstrap response to succeed, got ${response.status}`,
883859 });
......@@ -908,14 +884,14 @@ const splitHeaderTokens = (value: string | null) =>
908884 .filter((token) => token.length > 0)
909885 .toSorted();
910886
911const assertBrowserApiCorsHeaders = (headers: Headers) => {
912 assert.equal(headers.get("access-control-allow-origin"), "*");
913 assert.deepEqual(splitHeaderTokens(headers.get("access-control-allow-methods")), [
887const assertBrowserApiCorsHeaders = (headers: Readonly<Record<string, string | undefined>>) => {
888 assert.equal(headers["access-control-allow-origin"], "*");
889 assert.deepEqual(splitHeaderTokens(headers["access-control-allow-methods"] ?? null), [
914890 "GET",
915891 "OPTIONS",
916892 "POST",
917893 ]);
918 assert.deepEqual(splitHeaderTokens(headers.get("access-control-allow-headers")), [
894 assert.deepEqual(splitHeaderTokens(headers["access-control-allow-headers"] ?? null), [
919895 "authorization",
920896 "b3",
921897 "content-type",
......@@ -964,14 +940,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
964940 config: { devUrl: new URL("http://127.0.0.1:5173") },
965941 });
966942
967 const url = yield* getHttpServerUrl("/foo/bar?token=test-token");
968 const response = yield* Effect.promise(() => fetch(url, { redirect: "manual" }));
943 const response = yield* HttpClient.get("/foo/bar?token=test-token").pipe(
944 Effect.provideService(FetchHttpClient.RequestInit, { redirect: "manual" }),
945 );
969946
970947 assert.equal(response.status, 302);
971 assert.equal(
972 response.headers.get("location"),
973 "http://127.0.0.1:5173/foo/bar?token=test-token",
974 );
948 assert.equal(response.headers.location, "http://127.0.0.1:5173/foo/bar?token=test-token");
975949 }).pipe(Effect.provide(NodeHttpServer.layerTest)),
976950 );
977951
......@@ -1034,11 +1008,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
10341008 Effect.gen(function* () {
10351009 yield* buildAppUnderTest();
10361010
1037 const url = yield* getHttpServerUrl("/.well-known/t3/environment");
1038 const response = yield* Effect.promise(() => fetch(url));
1039 const body = (yield* Effect.promise(() =>
1040 response.json(),
1041 )) as typeof testEnvironmentDescriptor;
1011 const response = yield* HttpClient.get("/.well-known/t3/environment");
1012 const body = (yield* response.json) as typeof testEnvironmentDescriptor;
10421013
10431014 assert.equal(response.status, 200);
10441015 assert.deepEqual(body, testEnvironmentDescriptor);
......@@ -1049,17 +1020,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
10491020 Effect.gen(function* () {
10501021 yield* buildAppUnderTest();
10511022
1052 const url = yield* getHttpServerUrl("/.well-known/t3/environment");
1053 const response = yield* Effect.promise(() =>
1054 fetch(url, {
1055 headers: {
1056 origin: crossOriginClientOrigin,
1057 },
1058 }),
1059 );
1060 const body = (yield* Effect.promise(() =>
1061 response.json(),
1062 )) as typeof testEnvironmentDescriptor;
1023 const response = yield* HttpClient.get("/.well-known/t3/environment", {
1024 headers: {
1025 origin: crossOriginClientOrigin,
1026 },
1027 });
1028 const body = (yield* response.json) as typeof testEnvironmentDescriptor;
10631029
10641030 assert.equal(response.status, 200);
10651031 assertBrowserApiCorsHeaders(response.headers);
......@@ -1071,9 +1037,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
10711037 Effect.gen(function* () {
10721038 yield* buildAppUnderTest();
10731039
1074 const url = yield* getHttpServerUrl("/api/auth/session");
1075 const response = yield* Effect.promise(() => fetch(url));
1076 const body = (yield* Effect.promise(() => response.json())) as {
1040 const response = yield* HttpClient.get("/api/auth/session");
1041 const body = (yield* response.json) as {
10771042 readonly authenticated: boolean;
10781043 readonly auth: {
10791044 readonly policy: string;
......@@ -1111,15 +1076,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
11111076 assert.isUndefined((bootstrapBody as { readonly sessionToken?: string }).sessionToken);
11121077 assert.isDefined(setCookie);
11131078
1114 const sessionUrl = yield* getHttpServerUrl("/api/auth/session");
1115 const sessionResponse = yield* Effect.promise(() =>
1116 fetch(sessionUrl, {
1117 headers: {
1118 cookie: setCookie?.split(";")[0] ?? "",
1119 },
1120 }),
1121 );
1122 const sessionBody = (yield* Effect.promise(() => sessionResponse.json())) as {
1079 const sessionResponse = yield* HttpClient.get("/api/auth/session", {
1080 headers: {
1081 cookie: setCookie?.split(";")[0] ?? "",
1082 },
1083 });
1084 const sessionBody = (yield* sessionResponse.json) as {
11231085 readonly authenticated: boolean;
11241086 readonly sessionMethod?: string;
11251087 };
......@@ -1145,15 +1107,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
11451107 assert.equal(typeof bootstrapBody.sessionToken, "string");
11461108 assert.isTrue((bootstrapBody.sessionToken?.length ?? 0) > 0);
11471109
1148 const sessionUrl = yield* getHttpServerUrl("/api/auth/session");
1149 const sessionResponse = yield* Effect.promise(() =>
1150 fetch(sessionUrl, {
1151 headers: {
1152 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,
1153 },
1154 }),
1155 );
1156 const sessionBody = (yield* Effect.promise(() => sessionResponse.json())) as {
1110 const sessionResponse = yield* HttpClient.get("/api/auth/session", {
1111 headers: {
1112 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,
1113 },
1114 });
1115 const sessionBody = (yield* sessionResponse.json) as {
11571116 readonly authenticated: boolean;
11581117 readonly sessionMethod?: string;
11591118 };
......@@ -1169,16 +1128,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
11691128 yield* buildAppUnderTest();
11701129
11711130 const bearerToken = yield* getAuthenticatedBearerSessionToken();
1172 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");
1173 const wsTokenResponse = yield* Effect.promise(() =>
1174 fetch(wsTokenUrl, {
1175 method: "POST",
1176 headers: {
1177 authorization: `Bearer ${bearerToken}`,
1178 },
1179 }),
1180 );
1181 const wsTokenBody = (yield* Effect.promise(() => wsTokenResponse.json())) as {
1131 const wsTokenResponse = yield* HttpClient.post("/api/auth/ws-token", {
1132 headers: {
1133 authorization: `Bearer ${bearerToken}`,
1134 },
1135 });
1136 const wsTokenBody = (yield* wsTokenResponse.json) as {
11821137 readonly token: string;
11831138 readonly expiresAt: string;
11841139 };
......@@ -1207,16 +1162,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
12071162 assert.equal(bootstrapBody.authenticated, true);
12081163 assert.equal(typeof bootstrapBody.sessionToken, "string");
12091164
1210 const sessionUrl = yield* getHttpServerUrl("/api/auth/session");
1211 const sessionResponse = yield* Effect.promise(() =>
1212 fetch(sessionUrl, {
1213 headers: {
1214 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,
1215 origin,
1216 },
1217 }),
1218 );
1219 const sessionBody = (yield* Effect.promise(() => sessionResponse.json())) as {
1165 const sessionResponse = yield* HttpClient.get("/api/auth/session", {
1166 headers: {
1167 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,
1168 origin,
1169 },
1170 });
1171 const sessionBody = (yield* sessionResponse.json) as {
12201172 readonly authenticated: boolean;
12211173 readonly sessionMethod?: string;
12221174 };
......@@ -1226,17 +1178,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
12261178 assert.equal(sessionBody.authenticated, true);
12271179 assert.equal(sessionBody.sessionMethod, "bearer-session-token");
12281180
1229 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");
1230 const wsTokenResponse = yield* Effect.promise(() =>
1231 fetch(wsTokenUrl, {
1232 method: "POST",
1233 headers: {
1234 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,
1235 origin,
1236 },
1237 }),
1238 );
1239 const wsTokenBody = (yield* Effect.promise(() => wsTokenResponse.json())) as {
1181 const wsTokenResponse = yield* HttpClient.post("/api/auth/ws-token", {
1182 headers: {
1183 authorization: `Bearer ${bootstrapBody.sessionToken ?? ""}`,
1184 origin,
1185 },
1186 });
1187 const wsTokenBody = (yield* wsTokenResponse.json) as {
12401188 readonly token: string;
12411189 };
12421190
......@@ -1252,17 +1200,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
12521200 Effect.gen(function* () {
12531201 yield* buildAppUnderTest();
12541202
1255 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");
1256 const response = yield* Effect.promise(() =>
1257 fetch(wsTokenUrl, {
1258 method: "OPTIONS",
1259 headers: {
1260 origin: crossOriginClientOrigin,
1261 "access-control-request-method": "POST",
1262 "access-control-request-headers": "authorization",
1263 },
1264 }),
1265 );
1203 const response = yield* HttpClient.options("/api/auth/ws-token", {
1204 headers: {
1205 origin: crossOriginClientOrigin,
1206 "access-control-request-method": "POST",
1207 "access-control-request-headers": "authorization",
1208 },
1209 });
12661210
12671211 assert.equal(response.status, 204);
12681212 assertBrowserApiCorsHeaders(response.headers);
......@@ -1273,16 +1217,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
12731217 Effect.gen(function* () {
12741218 yield* buildAppUnderTest();
12751219
1276 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");
1277 const response = yield* Effect.promise(() =>
1278 fetch(wsTokenUrl, {
1279 method: "POST",
1280 headers: {
1281 origin: crossOriginClientOrigin,
1282 },
1283 }),
1284 );
1285 const body = (yield* Effect.promise(() => response.json())) as {
1220 const response = yield* HttpClient.post("/api/auth/ws-token", {
1221 headers: {
1222 origin: crossOriginClientOrigin,
1223 },
1224 });
1225 const body = (yield* response.json) as {
12861226 readonly error?: string;
12871227 };
12881228
......@@ -1357,17 +1297,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
13571297 readonly credential: string;
13581298 }>;
13591299
1360 const revokeUrl = yield* getHttpServerUrl("/api/auth/pairing-links/revoke");
1361 const revokeResponse = yield* Effect.promise(() =>
1362 fetch(revokeUrl, {
1363 method: "POST",
1364 headers: {
1365 cookie: ownerCookie,
1366 "content-type": "application/json",
1367 },
1368 body: JSON.stringify({ id: createdBody.id }),
1369 }),
1370 );
1300 const revokeResponse = yield* HttpClient.post("/api/auth/pairing-links/revoke", {
1301 headers: {
1302 cookie: ownerCookie,
1303 },
1304 body: yield* HttpBody.json({ id: createdBody.id }),
1305 });
13711306 const revokedBootstrap = yield* bootstrapBrowserSession(createdBody.credential);
13721307
13731308 assert.equal(createdResponse.status, 200);
......@@ -1420,20 +1355,13 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
14201355 });
14211356
14221357 const ownerCookie = yield* getAuthenticatedSessionCookieHeader();
1423 const pairingTokenUrl = yield* getHttpServerUrl("/api/auth/pairing-token");
1424 const ownerPairingResponse = yield* Effect.promise(() =>
1425 fetch(pairingTokenUrl, {
1426 method: "POST",
1427 headers: {
1428 cookie: ownerCookie,
1429 "content-type": "application/json",
1430 },
1431 body: JSON.stringify({
1432 label: "Julius iPhone",
1433 }),
1434 }),
1435 );
1436 const ownerPairingBody = (yield* Effect.promise(() => ownerPairingResponse.json())) as {
1358 const ownerPairingResponse = yield* HttpClient.post("/api/auth/pairing-token", {
1359 headers: {
1360 cookie: ownerCookie,
1361 },
1362 body: yield* HttpBody.json({ label: "Julius iPhone" }),
1363 });
1364 const ownerPairingBody = (yield* ownerPairingResponse.json) as {
14371365 readonly credential: string;
14381366 readonly label?: string;
14391367 };
......@@ -1448,17 +1376,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
14481376 assert.isDefined(pairedSessionCookie);
14491377
14501378 const pairedSessionCookieHeader = pairedSessionCookie ?? "";
1451 const listClientsUrl = yield* getHttpServerUrl("/api/auth/clients");
1452 const listBeforeResponse = yield* Effect.promise(() =>
1453 fetch(listClientsUrl, {
1454 headers: {
1455 cookie: ownerCookie,
1456 },
1457 }),
1458 );
1459 const clientsBefore = (yield* Effect.promise(() =>
1460 listBeforeResponse.json(),
1461 )) as ReadonlyArray<{
1379 const listBeforeResponse = yield* HttpClient.get("/api/auth/clients", {
1380 headers: {
1381 cookie: ownerCookie,
1382 },
1383 });
1384 const clientsBefore = (yield* listBeforeResponse.json) as ReadonlyArray<{
14621385 readonly sessionId: string;
14631386 readonly current: boolean;
14641387 readonly client: {
......@@ -1555,17 +1478,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
15551478 const pairedSessionId = clients.find((entry) => !entry.current)?.sessionId;
15561479 assert.isDefined(pairedSessionId);
15571480
1558 const revokeUrl = yield* getHttpServerUrl("/api/auth/clients/revoke");
1559 const revokeResponse = yield* Effect.promise(() =>
1560 fetch(revokeUrl, {
1561 method: "POST",
1562 headers: {
1563 cookie: ownerCookie,
1564 "content-type": "application/json",
1565 },
1566 body: JSON.stringify({ sessionId: pairedSessionId }),
1567 }),
1568 );
1481 const revokeResponse = yield* HttpClient.post("/api/auth/clients/revoke", {
1482 headers: {
1483 cookie: ownerCookie,
1484 },
1485 body: yield* HttpBody.json({ sessionId: pairedSessionId }),
1486 });
15691487 const pairedClientPairingResponse = yield* HttpClient.post("/api/auth/pairing-token", {
15701488 headers: {
15711489 cookie: pairedSessionCookie,
......@@ -1665,16 +1583,12 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
16651583 yield* buildAppUnderTest();
16661584
16671585 const bearerToken = yield* getAuthenticatedBearerSessionToken();
1668 const wsTokenUrl = yield* getHttpServerUrl("/api/auth/ws-token");
1669 const wsTokenResponse = yield* Effect.promise(() =>
1670 fetch(wsTokenUrl, {
1671 method: "POST",
1672 headers: {
1673 authorization: `Bearer ${bearerToken}`,
1674 },
1675 }),
1676 );
1677 const wsTokenBody = (yield* Effect.promise(() => wsTokenResponse.json())) as {
1586 const wsTokenResponse = yield* HttpClient.post("/api/auth/ws-token", {
1587 headers: {
1588 authorization: `Bearer ${bearerToken}`,
1589 },
1590 });
1591 const wsTokenBody = (yield* wsTokenResponse.json) as {
16781592 readonly token: string;
16791593 };
16801594 const wsUrl = `${yield* getWsServerUrl("/ws", { authenticated: false })}?wsToken=${encodeURIComponent(wsTokenBody.token)}`;
......@@ -1876,8 +1790,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
18761790 "content-type": "application/json",
18771791 origin: "http://localhost:5733",
18781792 },
1879 // @effect-diagnostics-next-line preferSchemaOverJson:off
1880 body: HttpBody.text(JSON.stringify(payload), "application/json"),
1793 body: yield* HttpBody.json(payload),
18811794 });
18821795
18831796 assert.equal(response.status, 204);
......@@ -1934,31 +1847,24 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
19341847 Effect.gen(function* () {
19351848 yield* buildAppUnderTest();
19361849
1937 const url = yield* getHttpServerUrl("/api/observability/v1/traces");
1938 const response = yield* Effect.promise(() =>
1939 fetch(url, {
1940 method: "OPTIONS",
1941 headers: {
1942 origin: "http://localhost:5733",
1943 "access-control-request-method": "POST",
1944 "access-control-request-headers": "content-type",
1945 },
1946 }),
1947 );
1850 const response = yield* HttpClient.options("/api/observability/v1/traces", {
1851 headers: {
1852 origin: "http://localhost:5733",
1853 "access-control-request-method": "POST",
1854 "access-control-request-headers": "content-type",
1855 },
1856 });
19481857
19491858 assert.equal(response.status, 204);
1950 assert.equal(response.headers.get("access-control-allow-origin"), "*");
1951 assert.deepEqual(splitHeaderTokens(response.headers.get("access-control-allow-methods")), [
1952 "GET",
1953 "OPTIONS",
1954 "POST",
1955 ]);
1956 assert.deepEqual(splitHeaderTokens(response.headers.get("access-control-allow-headers")), [
1957 "authorization",
1958 "b3",
1959 "content-type",
1960 "traceparent",
1961 ]);
1859 assert.equal(response.headers["access-control-allow-origin"], "*");
1860 assert.deepEqual(
1861 splitHeaderTokens(response.headers["access-control-allow-methods"] ?? null),
1862 ["GET", "OPTIONS", "POST"],
1863 );
1864 assert.deepEqual(
1865 splitHeaderTokens(response.headers["access-control-allow-headers"] ?? null),
1866 ["authorization", "b3", "content-type", "traceparent"],
1867 );
19621868 }).pipe(Effect.provide(NodeHttpServer.layerTest)),
19631869 );
19641870
......@@ -1995,8 +1901,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => {
19951901 cookie: yield* getAuthenticatedSessionCookieHeader(),
19961902 "content-type": "application/json",
19971903 },
1998 // @effect-diagnostics-next-line preferSchemaOverJson:off
1999 body: HttpBody.text(JSON.stringify(payload), "application/json"),
1904 body: yield* HttpBody.json(payload),
20001905 });
20011906
20021907 assert.equal(response.status, 204);
apps/server/src/serverRuntimeStartup.test.ts+53
......@@ -1,10 +1,12 @@
11import * as NodeServices from "@effect/platform-node/NodeServices";
22import { DEFAULT_MODEL, ProjectId, ProviderInstanceId, ThreadId } from "@t3tools/contracts";
33import { assert, it } from "@effect/vitest";
4import * as Crypto from "effect/Crypto";
45import * as Deferred from "effect/Deferred";
56import * as Effect from "effect/Effect";
67import * as Fiber from "effect/Fiber";
78import * as Option from "effect/Option";
9import * as PlatformError from "effect/PlatformError";
810import * as Ref from "effect/Ref";
911import * as Stream from "effect/Stream";
1012
......@@ -222,3 +224,54 @@ it.effect("resolveAutoBootstrapWelcomeTargets creates a project and thread when
222224 assert.deepStrictEqual(yield* Ref.get(dispatchCalls), ["project.create", "thread.create"]);
223225 }),
224226);
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";
1919import * as Scope from "effect/Scope";
2020import * as Context from "effect/Context";
2121import * as Console from "effect/Console";
22import * as Crypto from "effect/Crypto";
2223import * as DateTime from "effect/DateTime";
2324
2425import { ServerConfig } from "./config.ts";
......@@ -170,6 +171,8 @@ export const resolveWelcomeBase = Effect.gen(function* () {
170171});
171172
172173export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {
174 const crypto = yield* Crypto.Crypto;
175 const randomUUID = crypto.randomUUIDv4;
173176 const serverConfig = yield* ServerConfig;
174177 const projectionReadModelQuery = yield* ProjectionSnapshotQuery;
175178 const orchestrationEngine = yield* OrchestrationEngineService;
......@@ -188,12 +191,12 @@ export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {
188191
189192 if (Option.isNone(existingProject)) {
190193 const createdAt = DateTime.formatIso(yield* DateTime.now);
191 nextProjectId = ProjectId.make(crypto.randomUUID());
194 nextProjectId = ProjectId.make(yield* randomUUID);
192195 const bootstrapProjectTitle = path.basename(serverConfig.cwd) || "project";
193196 nextProjectDefaultModelSelection = getAutoBootstrapDefaultModelSelection();
194197 yield* orchestrationEngine.dispatch({
195198 type: "project.create",
196 commandId: CommandId.make(crypto.randomUUID()),
199 commandId: CommandId.make(yield* randomUUID),
197200 projectId: nextProjectId,
198201 title: bootstrapProjectTitle,
199202 workspaceRoot: serverConfig.cwd,
......@@ -210,10 +213,10 @@ export const resolveAutoBootstrapWelcomeTargets = Effect.gen(function* () {
210213 yield* projectionReadModelQuery.getFirstActiveThreadIdByProjectId(nextProjectId);
211214 if (Option.isNone(existingThreadId)) {
212215 const createdAt = DateTime.formatIso(yield* DateTime.now);
213 const createdThreadId = ThreadId.make(crypto.randomUUID());
216 const createdThreadId = ThreadId.make(yield* randomUUID);
214217 yield* orchestrationEngine.dispatch({
215218 type: "thread.create",
216 commandId: CommandId.make(crypto.randomUUID()),
219 commandId: CommandId.make(yield* randomUUID),
217220 threadId: createdThreadId,
218221 projectId: nextProjectId,
219222 title: "New thread",
apps/server/src/serverSettings.test.ts+13-11
......@@ -16,6 +16,9 @@ import * as Schema from "effect/Schema";
1616import { ServerConfig } from "./config.ts";
1717import { ServerSettingsLive, ServerSettingsService } from "./serverSettings.ts";
1818
19const decodeSettingsPatch = Schema.decodeUnknownEffect(ServerSettingsPatch);
20const decodeServerSettings = Schema.decodeUnknownEffect(ServerSettings);
21
1922const makeServerSettingsLayer = () =>
2023 ServerSettingsLive.pipe(
2124 Layer.provideMerge(
......@@ -29,15 +32,16 @@ const makeServerSettingsLayer = () =>
2932
3033it.layer(NodeServices.layer)("server settings", (it) => {
3134 it.effect("decodes nested settings patches", () =>
32 Effect.sync(() => {
33 const decodePatch = Schema.decodeUnknownSync(ServerSettingsPatch);
34
35 assert.deepEqual(decodePatch({ providers: { codex: { binaryPath: "/tmp/codex" } } }), {
36 providers: { codex: { binaryPath: "/tmp/codex" } },
37 });
35 Effect.gen(function* () {
36 assert.deepEqual(
37 yield* decodeSettingsPatch({ providers: { codex: { binaryPath: "/tmp/codex" } } }),
38 {
39 providers: { codex: { binaryPath: "/tmp/codex" } },
40 },
41 );
3842
3943 assert.deepEqual(
40 decodePatch({
44 yield* decodeSettingsPatch({
4145 textGenerationModelSelection: {
4246 options: [{ id: "fastMode", value: false }],
4347 },
......@@ -54,10 +58,8 @@ it.layer(NodeServices.layer)("server settings", (it) => {
5458 it.effect(
5559 "decodes legacy object-shaped textGenerationModelSelection.options from settings.json",
5660 () =>
57 Effect.sync(() => {
58 const decode = Schema.decodeUnknownSync(ServerSettings);
59
60 const decoded = decode({
61 Effect.gen(function* () {
62 const decoded = yield* decodeServerSettings({
6163 textGenerationModelSelection: {
6264 provider: ProviderDriverKind.make("codex"),
6365 model: "gpt-5.4-mini",
apps/server/src/sourceControl/AzureDevOpsCli.ts+1-1
......@@ -94,7 +94,7 @@ export interface AzureDevOpsCliShape {
9494}
9595
9696export class AzureDevOpsCli extends Context.Service<AzureDevOpsCli, AzureDevOpsCliShape>()(
97 "t3/source-control/AzureDevOpsCli",
97 "t3/sourceControl/AzureDevOpsCli",
9898) {}
9999
100100function errorText(error: VcsError | unknown): string {
apps/server/src/sourceControl/BitbucketApi.ts+1-1
......@@ -154,7 +154,7 @@ export interface BitbucketApiShape {
154154}
155155
156156export class BitbucketApi extends Context.Service<BitbucketApi, BitbucketApiShape>()(
157 "t3/source-control/BitbucketApi",
157 "t3/sourceControl/BitbucketApi",
158158) {}
159159
160160function nonEmpty(value: string | undefined): Option.Option<string> {
apps/server/src/sourceControl/GitHubCli.ts+1-1
......@@ -93,7 +93,7 @@ export interface GitHubCliShape {
9393}
9494
9595export class GitHubCli extends Context.Service<GitHubCli, GitHubCliShape>()(
96 "t3/source-control/GitHubCli",
96 "t3/sourceControl/GitHubCli",
9797) {}
9898
9999function errorText(error: VcsError | unknown): string {
apps/server/src/sourceControl/GitLabCli.ts+1-1
......@@ -97,7 +97,7 @@ export interface GitLabCliShape {
9797}
9898
9999export class GitLabCli extends Context.Service<GitLabCli, GitLabCliShape>()(
100 "t3/source-control/GitLabCli",
100 "t3/sourceControl/GitLabCli",
101101) {}
102102
103103function isVcsProcessSpawnError(error: unknown): boolean {
apps/server/src/sourceControl/SourceControlDiscovery.ts+1-1
......@@ -64,7 +64,7 @@ export interface SourceControlDiscoveryShape {
6464export class SourceControlDiscovery extends Context.Service<
6565 SourceControlDiscovery,
6666 SourceControlDiscoveryShape
67>()("t3/source-control/SourceControlDiscovery") {}
67>()("t3/sourceControl/SourceControlDiscovery") {}
6868
6969export const layer = Layer.effect(
7070 SourceControlDiscovery,
apps/server/src/sourceControl/SourceControlProvider.ts+1-1
......@@ -99,4 +99,4 @@ export interface SourceControlProviderShape {
9999export class SourceControlProvider extends Context.Service<
100100 SourceControlProvider,
101101 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 {
5151export class SourceControlProviderRegistry extends Context.Service<
5252 SourceControlProviderRegistry,
5353 SourceControlProviderRegistryShape
54>()("t3/source-control/SourceControlProviderRegistry") {}
54>()("t3/sourceControl/SourceControlProviderRegistry") {}
5555
5656function unsupportedProvider(
5757 kind: SourceControlProviderKind,
apps/server/src/sourceControl/SourceControlRepositoryService.ts+1-1
......@@ -39,7 +39,7 @@ export interface SourceControlRepositoryServiceShape {
3939export class SourceControlRepositoryService extends Context.Service<
4040 SourceControlRepositoryService,
4141 SourceControlRepositoryServiceShape
42>()("t3/source-control/SourceControlRepositoryService") {}
42>()("t3/sourceControl/SourceControlRepositoryService") {}
4343
4444function detailFromUnknown(cause: unknown): string {
4545 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
7676 operation: string,
7777 prefix: string,
7878 content: string,
79 ): Effect.Effect<string, TextGenerationError, Scope.Scope> => {
80 return Effect.gen(function* () {
81 return yield* fileSystem
82 .makeTempFileScoped({
83 prefix: `t3code-${prefix}-${process.pid}-`,
84 })
85 .pipe(Effect.tap((filePath) => fileSystem.writeFileString(filePath, content)));
86 }).pipe(
87 Effect.mapError(
88 (cause) =>
89 new TextGenerationError({
90 operation,
91 detail: `Failed to write temp file`,
92 cause,
93 }),
94 ),
95 );
96 };
79 ): Effect.Effect<string, TextGenerationError, Scope.Scope> =>
80 fileSystem
81 .makeTempFileScoped({
82 prefix: `t3code-${prefix}-${process.pid}-`,
83 })
84 .pipe(
85 Effect.tap((filePath) => fileSystem.writeFileString(filePath, content)),
86 Effect.mapError(
87 (cause) =>
88 new TextGenerationError({
89 operation,
90 detail: `Failed to write temp file`,
91 cause,
92 }),
93 ),
94 );
9795
9896 const safeUnlink = (filePath: string): Effect.Effect<void, never> =>
9997 fileSystem.remove(filePath).pipe(Effect.catch(() => Effect.void));
apps/server/src/textGeneration/TextGeneration.ts+1-1
......@@ -116,7 +116,7 @@ export interface TextGenerationShape {
116116 * TextGeneration - Service tag for commit and PR text generation.
117117 */
118118export class TextGeneration extends Context.Service<TextGeneration, TextGenerationShape>()(
119 "t3/text-generation/TextGeneration",
119 "t3/textGeneration/TextGeneration",
120120) {}
121121
122122type TextGenerationOp =
apps/server/src/ws.ts+49-32
......@@ -1,4 +1,5 @@
11import * as Cause from "effect/Cause";
2import * as Crypto from "effect/Crypto";
23import * as DateTime from "effect/DateTime";
34import * as Duration from "effect/Duration";
45import * as Effect from "effect/Effect";
......@@ -160,6 +161,7 @@ function toAuthAccessStreamEvent(
160161const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
161162 WsRpcGroup.toLayer(
162163 Effect.gen(function* () {
164 const crypto = yield* Crypto.Crypto;
163165 const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
164166 const orchestrationEngine = yield* OrchestrationEngineService;
165167 const checkpointDiffQuery = yield* CheckpointDiffQuery;
......@@ -195,8 +197,21 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
195197 const sessions = yield* SessionCredentialService;
196198 const processDiagnostics = yield* ProcessDiagnostics.ProcessDiagnostics;
197199 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));
198213 const serverCommandId = (tag: string) =>
199 CommandId.make(`server:${tag}:${crypto.randomUUID()}`);
214 randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`)));
200215
201216 const loadAuthAccessSnapshot = () =>
202217 Effect.all({
......@@ -212,29 +227,28 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
212227 readonly payload: Record<string, unknown>;
213228 readonly tone: "info" | "error";
214229 }) =>
215 orchestrationEngine.dispatch({
216 type: "thread.activity.append",
230 Effect.all({
217231 commandId: serverCommandId("setup-script-activity"),
218 threadId: input.threadId,
219 activity: {
220 id: EventId.make(crypto.randomUUID()),
221 tone: input.tone,
222 kind: input.kind,
223 summary: input.summary,
224 payload: input.payload,
225 turnId: null,
226 createdAt: input.createdAt,
227 },
228 createdAt: input.createdAt,
229 });
230
231 const toDispatchCommandError = (cause: unknown, fallbackMessage: string) =>
232 isOrchestrationDispatchCommandError(cause)
233 ? cause
234 : new OrchestrationDispatchCommandError({
235 message: cause instanceof Error ? cause.message : fallbackMessage,
236 cause,
237 });
232 activityId: serverEventId,
233 }).pipe(
234 Effect.flatMap(({ commandId, activityId }) =>
235 orchestrationEngine.dispatch({
236 type: "thread.activity.append",
237 commandId,
238 threadId: input.threadId,
239 activity: {
240 id: activityId,
241 tone: input.tone,
242 kind: input.kind,
243 summary: input.summary,
244 payload: input.payload,
245 turnId: null,
246 createdAt: input.createdAt,
247 },
248 createdAt: input.createdAt,
249 }),
250 ),
251 );
238252
239253 const toBootstrapDispatchCommandCauseError = (cause: Cause.Cause<unknown>) => {
240254 const error = Cause.squash(cause);
......@@ -370,13 +384,16 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
370384
371385 const cleanupCreatedThread = () =>
372386 createdThread
373 ? orchestrationEngine
374 .dispatch({
375 type: "thread.delete",
376 commandId: serverCommandId("bootstrap-thread-delete"),
377 threadId: command.threadId,
378 })
379 .pipe(Effect.ignoreCause({ log: true }))
387 ? serverCommandId("bootstrap-thread-delete").pipe(
388 Effect.flatMap((commandId) =>
389 orchestrationEngine.dispatch({
390 type: "thread.delete",
391 commandId,
392 threadId: command.threadId,
393 }),
394 ),
395 Effect.ignoreCause({ log: true }),
396 )
380397 : Effect.void;
381398
382399 const recordSetupScriptLaunchFailure = (input: {
......@@ -499,7 +516,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
499516 if (bootstrap?.createThread) {
500517 yield* orchestrationEngine.dispatch({
501518 type: "thread.create",
502 commandId: serverCommandId("bootstrap-thread-create"),
519 commandId: yield* serverCommandId("bootstrap-thread-create"),
503520 threadId: command.threadId,
504521 projectId: bootstrap.createThread.projectId,
505522 title: bootstrap.createThread.title,
......@@ -523,7 +540,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) =>
523540 targetWorktreePath = worktree.worktree.path;
524541 yield* orchestrationEngine.dispatch({
525542 type: "thread.meta.update",
526 commandId: serverCommandId("bootstrap-thread-meta-update"),
543 commandId: yield* serverCommandId("bootstrap-thread-meta-update"),
527544 threadId: command.threadId,
528545 branch: worktree.worktree.refName,
529546 worktreePath: targetWorktreePath,
apps/server/tsconfig.json-1
......@@ -1,7 +1,6 @@
11{
22 "extends": "../../tsconfig.base.json",
33 "compilerOptions": {
4 "composite": true,
54 "types": ["node", "bun"],
65 "lib": ["ESNext", "esnext.disposable"]
76 },
apps/web/package.json+1-3
......@@ -7,7 +7,7 @@
77 "dev": "vite",
88 "build": "vite build",
99 "preview": "vite preview",
10 "typecheck": "tsc --noEmit",
10 "typecheck": "tsgo --noEmit",
1111 "test": "vitest run --passWithNoTests",
1212 "test:browser": "vitest run --config vitest.browser.config.ts",
1313 "test:browser:install": "playwright install --with-deps chromium"
......@@ -43,7 +43,6 @@
4343 "zustand": "^5.0.11"
4444 },
4545 "devDependencies": {
46 "@effect/language-service": "catalog:",
4746 "@rolldown/plugin-babel": "^0.2.0",
4847 "@tailwindcss/vite": "^4.0.0",
4948 "@tanstack/router-plugin": "^1.161.0",
......@@ -57,7 +56,6 @@
5756 "msw": "2.12.11",
5857 "playwright": "^1.58.2",
5958 "tailwindcss": "^4.0.0",
60 "typescript": "catalog:",
6159 "vite": "^8.0.0",
6260 "vitest": "catalog:",
6361 "vitest-browser-react": "^2.0.5"
apps/web/src/session-logic.test.ts+3-1
......@@ -22,6 +22,8 @@ import {
2222 isLatestTurnSettled,
2323} from "./session-logic";
2424
25let nextActivityId = 0;
26
2527function makeActivity(overrides: {
2628 id?: string;
2729 createdAt?: string;
......@@ -34,7 +36,7 @@ function makeActivity(overrides: {
3436}): OrchestrationThreadActivity {
3537 const payload = overrides.payload ?? {};
3638 return {
37 id: EventId.make(overrides.id ?? crypto.randomUUID()),
39 id: EventId.make(overrides.id ?? `activity-${nextActivityId++}`),
3840 createdAt: overrides.createdAt ?? "2026-02-23T00:00:00.000Z",
3941 kind: overrides.kind ?? "tool.started",
4042 summary: overrides.summary ?? "Tool call",
apps/web/tsconfig.json+6-15
......@@ -15,22 +15,13 @@
1515 "plugins": [
1616 {
1717 "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.
1919 "diagnosticSeverity": {
20 "importFromBarrel": "error",
21 "anyUnknownInErrorContext": "error",
22 "unsafeEffectTypeAssertion": "error",
23 "instanceOfSchema": "error",
24 "deterministicKeys": "error",
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"
20 "globalDate": "off",
21 "globalConsole": "off",
22 "globalRandom": "off",
23 "globalTimers": "off",
24 "globalFetch": "off"
3425 }
3526 }
3627 ]
bun.lock+40-31
......@@ -5,13 +5,13 @@
55 "": {
66 "name": "@t3tools/monorepo",
77 "devDependencies": {
8 "@effect/language-service": "catalog:",
8 "@effect/tsgo": "catalog:",
99 "@oxlint/plugins": "^1.63.0",
1010 "@types/node": "catalog:",
11 "@typescript/native-preview": "catalog:",
1112 "oxfmt": "^0.40.0",
1213 "oxlint": "^1.63.0",
1314 "turbo": "^2.3.3",
14 "typescript": "catalog:",
1515 "vitest": "catalog:",
1616 },
1717 },
......@@ -29,11 +29,9 @@
2929 "electron-updater": "^6.6.2",
3030 },
3131 "devDependencies": {
32 "@effect/language-service": "catalog:",
3332 "@effect/vitest": "catalog:",
3433 "@types/node": "catalog:",
3534 "tsdown": "catalog:",
36 "typescript": "catalog:",
3735 "vitest": "catalog:",
3836 },
3937 },
......@@ -66,7 +64,6 @@
6664 "node-pty": "^1.1.0",
6765 },
6866 "devDependencies": {
69 "@effect/language-service": "catalog:",
7067 "@effect/vitest": "catalog:",
7168 "@t3tools/contracts": "workspace:*",
7269 "@t3tools/shared": "workspace:*",
......@@ -77,7 +74,6 @@
7774 "effect-acp": "workspace:*",
7875 "effect-codex-app-server": "workspace:*",
7976 "tsdown": "catalog:",
80 "typescript": "catalog:",
8177 "vitest": "catalog:",
8278 },
8379 },
......@@ -115,7 +111,6 @@
115111 "zustand": "^5.0.11",
116112 },
117113 "devDependencies": {
118 "@effect/language-service": "catalog:",
119114 "@rolldown/plugin-babel": "^0.2.0",
120115 "@tailwindcss/vite": "^4.0.0",
121116 "@tanstack/router-plugin": "^1.161.0",
......@@ -129,7 +124,6 @@
129124 "msw": "2.12.11",
130125 "playwright": "^1.58.2",
131126 "tailwindcss": "^4.0.0",
132 "typescript": "catalog:",
133127 "vite": "^8.0.0",
134128 "vitest": "catalog:",
135129 "vitest-browser-react": "^2.0.5",
......@@ -143,10 +137,8 @@
143137 "effect": "catalog:",
144138 },
145139 "devDependencies": {
146 "@effect/language-service": "catalog:",
147140 "@effect/vitest": "catalog:",
148141 "@types/bun": "catalog:",
149 "typescript": "catalog:",
150142 "vitest": "catalog:",
151143 },
152144 },
......@@ -158,8 +150,6 @@
158150 "effect": "catalog:",
159151 },
160152 "devDependencies": {
161 "@effect/language-service": "catalog:",
162 "typescript": "catalog:",
163153 "vitest": "catalog:",
164154 },
165155 },
......@@ -170,9 +160,7 @@
170160 "effect": "catalog:",
171161 },
172162 "devDependencies": {
173 "@effect/language-service": "catalog:",
174163 "@effect/vitest": "catalog:",
175 "typescript": "catalog:",
176164 "vitest": "catalog:",
177165 },
178166 },
......@@ -182,11 +170,10 @@
182170 "effect": "catalog:",
183171 },
184172 "devDependencies": {
185 "@effect/language-service": "catalog:",
186173 "@effect/openapi-generator": "catalog:",
187174 "@effect/platform-node": "catalog:",
188175 "@effect/vitest": "catalog:",
189 "typescript": "catalog:",
176 "@types/node": "catalog:",
190177 "vitest": "catalog:",
191178 },
192179 },
......@@ -196,11 +183,10 @@
196183 "effect": "catalog:",
197184 },
198185 "devDependencies": {
199 "@effect/language-service": "catalog:",
200186 "@effect/openapi-generator": "catalog:",
201187 "@effect/platform-node": "catalog:",
202188 "@effect/vitest": "catalog:",
203 "typescript": "catalog:",
189 "@types/node": "catalog:",
204190 "vitest": "catalog:",
205191 },
206192 },
......@@ -211,11 +197,9 @@
211197 "effect": "catalog:",
212198 },
213199 "devDependencies": {
214 "@effect/language-service": "catalog:",
215200 "@effect/platform-node": "catalog:",
216201 "@effect/vitest": "catalog:",
217202 "@types/node": "catalog:",
218 "typescript": "catalog:",
219203 "vitest": "catalog:",
220204 },
221205 },
......@@ -227,11 +211,9 @@
227211 "effect": "catalog:",
228212 },
229213 "devDependencies": {
230 "@effect/language-service": "catalog:",
231214 "@effect/platform-node": "catalog:",
232215 "@effect/vitest": "catalog:",
233216 "@types/node": "catalog:",
234 "typescript": "catalog:",
235217 "vitest": "catalog:",
236218 },
237219 },
......@@ -242,10 +224,8 @@
242224 "effect": "catalog:",
243225 },
244226 "devDependencies": {
245 "@effect/language-service": "catalog:",
246227 "@effect/vitest": "catalog:",
247228 "@types/node": "catalog:",
248 "typescript": "catalog:",
249229 "vitest": "catalog:",
250230 },
251231 },
......@@ -259,10 +239,8 @@
259239 "effect": "catalog:",
260240 },
261241 "devDependencies": {
262 "@effect/language-service": "catalog:",
263242 "@effect/vitest": "catalog:",
264243 "@types/bun": "catalog:",
265 "typescript": "catalog:",
266244 "vitest": "catalog:",
267245 },
268246 },
......@@ -286,19 +264,20 @@
286264 },
287265 "catalog": {
288266 "@effect/atom-react": "4.0.0-beta.73",
289 "@effect/language-service": "0.84.2",
290267 "@effect/openapi-generator": "4.0.0-beta.73",
291268 "@effect/platform-bun": "4.0.0-beta.73",
292269 "@effect/platform-node": "4.0.0-beta.73",
293270 "@effect/platform-node-shared": "4.0.0-beta.73",
294271 "@effect/sql-sqlite-bun": "4.0.0-beta.73",
272 "@effect/tsgo": "0.11.4",
295273 "@effect/vitest": "4.0.0-beta.73",
296274 "@pierre/diffs": "1.1.20",
297275 "@types/bun": "^1.3.11",
298276 "@types/node": "^24.10.13",
277 "@typescript/native-preview": "7.0.0-dev.20260527.2",
299278 "effect": "4.0.0-beta.73",
300279 "tsdown": "^0.20.3",
301 "typescript": "^5.7.3",
280 "typescript": "~6.0.3",
302281 "vitest": "^4.0.0",
303282 },
304283 "packages": {
......@@ -402,8 +381,6 @@
402381
403382 "@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
407384 "@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
409386 "@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 @@
414391
415392 "@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
417410 "@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
419412 "@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 @@
934927
935928 "@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
937946 "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
938947
939948 "@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 @@
19821991
19831992 "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
19871996 "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 @@
33 "private": true,
44 "type": "module",
55 "scripts": {
6 "typecheck": "tsc --noEmit",
6 "typecheck": "tsgo --noEmit",
77 "test": "vitest run"
88 },
99 "dependencies": {
......@@ -12,10 +12,8 @@
1212 "effect": "catalog:"
1313 },
1414 "devDependencies": {
15 "@effect/language-service": "catalog:",
1615 "@effect/vitest": "catalog:",
1716 "@types/bun": "catalog:",
18 "typescript": "catalog:",
1917 "vitest": "catalog:"
2018 }
2119}
package.json+6-5
......@@ -17,18 +17,19 @@
1717 "@effect/platform-node-shared": "4.0.0-beta.73",
1818 "@effect/sql-sqlite-bun": "4.0.0-beta.73",
1919 "@effect/vitest": "4.0.0-beta.73",
20 "@effect/language-service": "0.84.2",
20 "@effect/tsgo": "0.11.4",
2121 "@pierre/diffs": "1.1.20",
2222 "@types/bun": "^1.3.11",
2323 "@types/node": "^24.10.13",
24 "@typescript/native-preview": "7.0.0-dev.20260527.2",
2425 "tsdown": "^0.20.3",
25 "typescript": "^5.7.3",
26 "typescript": "~6.0.3",
2627 "vitest": "^4.0.0"
2728 }
2829 },
2930 "type": "module",
3031 "scripts": {
31 "prepare": "effect-language-service patch",
32 "prepare": "effect-tsgo patch",
3233 "dev": "node scripts/dev-runner.ts dev",
3334 "dev:server": "node scripts/dev-runner.ts dev:server",
3435 "dev:web": "node scripts/dev-runner.ts dev:web",
......@@ -61,13 +62,13 @@
6162 "sync:vscode-icons": "node scripts/sync-vscode-icons.mjs"
6263 },
6364 "devDependencies": {
64 "@effect/language-service": "catalog:",
65 "@effect/tsgo": "catalog:",
6566 "@oxlint/plugins": "^1.63.0",
6667 "@types/node": "catalog:",
68 "@typescript/native-preview": "catalog:",
6769 "oxfmt": "^0.40.0",
6870 "oxlint": "^1.63.0",
6971 "turbo": "^2.3.3",
70 "typescript": "catalog:",
7172 "vitest": "catalog:"
7273 },
7374 "overrides": {
packages/client-runtime/package.json+1-3
......@@ -9,7 +9,7 @@
99 }
1010 },
1111 "scripts": {
12 "typecheck": "tsc --noEmit",
12 "typecheck": "tsgo --noEmit",
1313 "test": "vitest run"
1414 },
1515 "dependencies": {
......@@ -18,8 +18,6 @@
1818 "effect": "catalog:"
1919 },
2020 "devDependencies": {
21 "@effect/language-service": "catalog:",
22 "typescript": "catalog:",
2321 "vitest": "catalog:"
2422 }
2523}
packages/contracts/package.json+1-3
......@@ -17,16 +17,14 @@
1717 }
1818 },
1919 "scripts": {
20 "typecheck": "tsc --noEmit",
20 "typecheck": "tsgo --noEmit",
2121 "test": "vitest run"
2222 },
2323 "dependencies": {
2424 "effect": "catalog:"
2525 },
2626 "devDependencies": {
27 "@effect/language-service": "catalog:",
2827 "@effect/vitest": "catalog:",
29 "typescript": "catalog:",
3028 "vitest": "catalog:"
3129 }
3230}
packages/contracts/src/orchestration.test.ts+4-3
......@@ -1,5 +1,4 @@
1import assert from "node:assert/strict";
2import { it } from "@effect/vitest";
1import { assert, it } from "@effect/vitest";
32import * as Effect from "effect/Effect";
43import * as Schema from "effect/Schema";
54
......@@ -379,7 +378,9 @@ it.effect("decodes thread archived and unarchived events", () =>
379378 },
380379 });
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 }
383384 assert.strictEqual(archived.payload.archivedAt, "2026-01-01T00:00:00.000Z");
384385 assert.strictEqual(unarchived.type, "thread.unarchived");
385386 }),
packages/effect-acp/package.json+2-3
......@@ -33,7 +33,7 @@
3333 }
3434 },
3535 "scripts": {
36 "typecheck": "tsc --noEmit",
36 "typecheck": "tsgo --noEmit",
3737 "test": "vitest run",
3838 "generate": "bun run scripts/generate.ts"
3939 },
......@@ -41,11 +41,10 @@
4141 "effect": "catalog:"
4242 },
4343 "devDependencies": {
44 "@effect/language-service": "catalog:",
4544 "@effect/openapi-generator": "catalog:",
4645 "@effect/platform-node": "catalog:",
4746 "@effect/vitest": "catalog:",
48 "typescript": "catalog:",
47 "@types/node": "catalog:",
4948 "vitest": "catalog:"
5049 }
5150}
packages/effect-acp/scripts/generate.ts+3-6
......@@ -146,7 +146,7 @@ function collectSchemaEntries(
146146 return entries;
147147}
148148
149function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.Json.Type {
149function normalizeNullableTypes(value: Schema.Json): Schema.Json {
150150 if (Array.isArray(value)) {
151151 return value.map(normalizeNullableTypes);
152152 }
......@@ -158,10 +158,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
158158 key,
159159 normalizeNullableTypes(child),
160160 ]);
161 const normalizedObject = Object.fromEntries(normalizedEntries) as Record<
162 string,
163 typeof Schema.Json.Type
164 >;
161 const normalizedObject = Object.fromEntries(normalizedEntries) as Record<string, Schema.Json>;
165162 const typeValue = normalizedObject.type;
166163
167164 if (!Array.isArray(typeValue)) {
......@@ -179,7 +176,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
179176 }
180177 const nonNullType = nonNullTypes[0]!;
181178
182 const nextObject: Record<string, typeof Schema.Json.Type> = {};
179 const nextObject: Record<string, Schema.Json> = {};
183180 for (const [key, child] of Object.entries(normalizedObject)) {
184181 if (key !== "type") {
185182 nextObject[key] = child;
packages/effect-acp/src/agent.ts+3-1
......@@ -207,7 +207,9 @@ export interface AcpAgentShape {
207207 ) => Effect.Effect<void>;
208208}
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
212214interface AcpCoreAgentRequestHandlers {
213215 initialize?: (
packages/effect-acp/src/client.ts+1-1
......@@ -263,7 +263,7 @@ export interface AcpClientShape {
263263}
264264
265265export class AcpClient extends Context.Service<AcpClient, AcpClientShape>()(
266 "effect-acp/AcpClient",
266 "effect-acp/client/AcpClient",
267267) {}
268268
269269interface AcpCoreRequestHandlers {
packages/effect-acp/src/protocol.ts+2-2
......@@ -29,12 +29,12 @@ export type AcpIncomingNotification =
2929 | {
3030 readonly _tag: "SessionUpdate";
3131 readonly method: typeof CLIENT_METHODS.session_update;
32 readonly params: typeof AcpSchema.SessionNotification.Type;
32 readonly params: AcpSchema.SessionNotification;
3333 }
3434 | {
3535 readonly _tag: "ElicitationComplete";
3636 readonly method: typeof CLIENT_METHODS.session_elicitation_complete;
37 readonly params: typeof AcpSchema.ElicitationCompleteNotification.Type;
37 readonly params: AcpSchema.ElicitationCompleteNotification;
3838 }
3939 | {
4040 readonly _tag: "ExtNotification";
packages/effect-acp/tsconfig.json+3-1
......@@ -1,5 +1,7 @@
11{
22 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},
3 "compilerOptions": {
4 "types": ["node"]
5 },
46 "include": ["src", "scripts", "test"]
57}
packages/effect-codex-app-server/package.json+2-3
......@@ -25,7 +25,7 @@
2525 }
2626 },
2727 "scripts": {
28 "typecheck": "tsc --noEmit",
28 "typecheck": "tsgo --noEmit",
2929 "test": "vitest run",
3030 "generate": "bun run scripts/generate.ts",
3131 "probe": "bun run test/examples/codex-app-server-probe.ts"
......@@ -34,11 +34,10 @@
3434 "effect": "catalog:"
3535 },
3636 "devDependencies": {
37 "@effect/language-service": "catalog:",
3837 "@effect/openapi-generator": "catalog:",
3938 "@effect/platform-node": "catalog:",
4039 "@effect/vitest": "catalog:",
41 "typescript": "catalog:",
40 "@types/node": "catalog:",
4241 "vitest": "catalog:"
4342 }
4443}
packages/effect-codex-app-server/scripts/generate.ts+12-15
......@@ -70,7 +70,7 @@ class GeneratorError extends Schema.TaggedErrorClass<GeneratorError>()("Generato
7070 }
7171}
7272
73const ManualSchemas: Record<string, typeof Schema.Json.Type> = {
73const ManualSchemas: Record<string, Schema.Json> = {
7474 GetAuthStatusParams: {
7575 type: "object",
7676 title: "GetAuthStatusParams",
......@@ -218,7 +218,7 @@ function collectSchemaEntries(
218218 return entries;
219219}
220220
221function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.Json.Type {
221function normalizeNullableTypes(value: Schema.Json): Schema.Json {
222222 if (Array.isArray(value)) {
223223 return value.map(normalizeNullableTypes);
224224 }
......@@ -230,10 +230,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
230230 key,
231231 normalizeNullableTypes(child),
232232 ]);
233 const normalizedObject = Object.fromEntries(normalizedEntries) as Record<
234 string,
235 typeof Schema.Json.Type
236 >;
233 const normalizedObject = Object.fromEntries(normalizedEntries) as Record<string, Schema.Json>;
237234 const typeValue = normalizedObject.type;
238235
239236 if (!Array.isArray(typeValue)) {
......@@ -251,7 +248,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
251248 }
252249 const nonNullType = nonNullTypes[0]!;
253250
254 const nextObject: Record<string, typeof Schema.Json.Type> = {};
251 const nextObject: Record<string, Schema.Json> = {};
255252 for (const [key, child] of Object.entries(normalizedObject)) {
256253 if (key !== "type") {
257254 nextObject[key] = child;
......@@ -269,7 +266,7 @@ function normalizeNullableTypes(value: typeof Schema.Json.Type): typeof Schema.J
269266 };
270267}
271268
272function stripNullDefaults(value: typeof Schema.Json.Type): typeof Schema.Json.Type {
269function stripNullDefaults(value: Schema.Json): Schema.Json {
273270 if (Array.isArray(value)) {
274271 return value.map(stripNullDefaults);
275272 }
......@@ -281,7 +278,7 @@ function stripNullDefaults(value: typeof Schema.Json.Type): typeof Schema.Json.T
281278 Object.entries(value)
282279 .filter(([key, child]) => !(key === "default" && child === null))
283280 .map(([key, child]) => [key, stripNullDefaults(child)]),
284 ) as typeof Schema.Json.Type;
281 ) as Schema.Json;
285282}
286283
287284function toPascalCaseMethod(method: string) {
......@@ -417,7 +414,7 @@ function renderSchemaMap(
417414}
418415
419416function renderSchemaTypeReference(schemaName: string) {
420 return schemaName === "undefined" ? "undefined" : `typeof CodexSchema.${schemaName}.Type`;
417 return schemaName === "undefined" ? "undefined" : `CodexSchema.${schemaName}`;
421418}
422419
423420function exportNameForPath(filePath: string): string {
......@@ -468,11 +465,11 @@ function buildJsonSchemaFiles(
468465}
469466
470467function rewriteExternalRefs(
471 value: typeof Schema.Json.Type,
468 value: Schema.Json,
472469 localDefinitionNames: ReadonlyMap<string, string>,
473470 currentNamespace: string | undefined,
474471 exportNameByQualifiedName: ReadonlyMap<string, string>,
475): typeof Schema.Json.Type {
472): Schema.Json {
476473 if (Array.isArray(value)) {
477474 return value.map((entry) =>
478475 rewriteExternalRefs(entry, localDefinitionNames, currentNamespace, exportNameByQualifiedName),
......@@ -522,7 +519,7 @@ function rewriteExternalRefs(
522519 ),
523520 ];
524521 }),
525 ) as typeof Schema.Json.Type;
522 ) as Schema.Json;
526523}
527524
528525const generateFiles = Effect.fn("generateFiles")(function* () {
......@@ -543,7 +540,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () {
543540 const exportNameByQualifiedName = new Map(
544541 jsonSchemaFiles.map((file) => [file.qualifiedName, file.exportName]),
545542 );
546 const aggregateSchemas: Record<string, typeof Schema.Json.Type> = {};
543 const aggregateSchemas: Record<string, Schema.Json> = {};
547544
548545 for (const file of jsonSchemaFiles) {
549546 const raw = yield* fetchText(file.downloadUrl);
......@@ -568,7 +565,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () {
568565 );
569566 }
570567
571 const topLevelSchema: Record<string, typeof Schema.Json.Type> = {};
568 const topLevelSchema: Record<string, Schema.Json> = {};
572569 for (const [key, value] of Object.entries(parsed)) {
573570 if (key !== "definitions") {
574571 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;
173173export type ServerNotificationMethod = keyof typeof SERVER_NOTIFICATION_METHODS;
174174
175175export interface ClientRequestParamsByMethod {
176 readonly initialize: typeof CodexSchema.V1InitializeParams.Type;
177 readonly "thread/start": typeof CodexSchema.V2ThreadStartParams.Type;
178 readonly "thread/resume": typeof CodexSchema.V2ThreadResumeParams.Type;
179 readonly "thread/fork": typeof CodexSchema.V2ThreadForkParams.Type;
180 readonly "thread/archive": typeof CodexSchema.V2ThreadArchiveParams.Type;
181 readonly "thread/unsubscribe": typeof CodexSchema.V2ThreadUnsubscribeParams.Type;
182 readonly "thread/name/set": typeof CodexSchema.V2ThreadSetNameParams.Type;
183 readonly "thread/metadata/update": typeof CodexSchema.V2ThreadMetadataUpdateParams.Type;
184 readonly "thread/unarchive": typeof CodexSchema.V2ThreadUnarchiveParams.Type;
185 readonly "thread/compact/start": typeof CodexSchema.V2ThreadCompactStartParams.Type;
186 readonly "thread/shellCommand": typeof CodexSchema.V2ThreadShellCommandParams.Type;
187 readonly "thread/approveGuardianDeniedAction": typeof CodexSchema.V2ThreadApproveGuardianDeniedActionParams.Type;
188 readonly "thread/rollback": typeof CodexSchema.V2ThreadRollbackParams.Type;
189 readonly "thread/list": typeof CodexSchema.V2ThreadListParams.Type;
190 readonly "thread/loaded/list": typeof CodexSchema.V2ThreadLoadedListParams.Type;
191 readonly "thread/read": typeof CodexSchema.V2ThreadReadParams.Type;
192 readonly "thread/inject_items": typeof CodexSchema.V2ThreadInjectItemsParams.Type;
193 readonly "skills/list": typeof CodexSchema.V2SkillsListParams.Type;
194 readonly "hooks/list": typeof CodexSchema.V2HooksListParams.Type;
195 readonly "marketplace/add": typeof CodexSchema.V2MarketplaceAddParams.Type;
196 readonly "marketplace/remove": typeof CodexSchema.V2MarketplaceRemoveParams.Type;
197 readonly "marketplace/upgrade": typeof CodexSchema.V2MarketplaceUpgradeParams.Type;
198 readonly "plugin/list": typeof CodexSchema.V2PluginListParams.Type;
199 readonly "plugin/read": typeof CodexSchema.V2PluginReadParams.Type;
200 readonly "plugin/skill/read": typeof CodexSchema.V2PluginSkillReadParams.Type;
201 readonly "plugin/share/save": typeof CodexSchema.V2PluginShareSaveParams.Type;
202 readonly "plugin/share/updateTargets": typeof CodexSchema.V2PluginShareUpdateTargetsParams.Type;
203 readonly "plugin/share/list": typeof CodexSchema.V2PluginShareListParams.Type;
204 readonly "plugin/share/delete": typeof CodexSchema.V2PluginShareDeleteParams.Type;
205 readonly "app/list": typeof CodexSchema.V2AppsListParams.Type;
206 readonly "fs/readFile": typeof CodexSchema.V2FsReadFileParams.Type;
207 readonly "fs/writeFile": typeof CodexSchema.V2FsWriteFileParams.Type;
208 readonly "fs/createDirectory": typeof CodexSchema.V2FsCreateDirectoryParams.Type;
209 readonly "fs/getMetadata": typeof CodexSchema.V2FsGetMetadataParams.Type;
210 readonly "fs/readDirectory": typeof CodexSchema.V2FsReadDirectoryParams.Type;
211 readonly "fs/remove": typeof CodexSchema.V2FsRemoveParams.Type;
212 readonly "fs/copy": typeof CodexSchema.V2FsCopyParams.Type;
213 readonly "fs/watch": typeof CodexSchema.V2FsWatchParams.Type;
214 readonly "fs/unwatch": typeof CodexSchema.V2FsUnwatchParams.Type;
215 readonly "skills/config/write": typeof CodexSchema.V2SkillsConfigWriteParams.Type;
216 readonly "plugin/install": typeof CodexSchema.V2PluginInstallParams.Type;
217 readonly "plugin/uninstall": typeof CodexSchema.V2PluginUninstallParams.Type;
218 readonly "turn/start": typeof CodexSchema.V2TurnStartParams.Type;
219 readonly "turn/steer": typeof CodexSchema.V2TurnSteerParams.Type;
220 readonly "turn/interrupt": typeof CodexSchema.V2TurnInterruptParams.Type;
221 readonly "review/start": typeof CodexSchema.V2ReviewStartParams.Type;
222 readonly "model/list": typeof CodexSchema.V2ModelListParams.Type;
223 readonly "modelProvider/capabilities/read": typeof CodexSchema.V2ModelProviderCapabilitiesReadParams.Type;
224 readonly "experimentalFeature/list": typeof CodexSchema.V2ExperimentalFeatureListParams.Type;
225 readonly "experimentalFeature/enablement/set": typeof CodexSchema.V2ExperimentalFeatureEnablementSetParams.Type;
226 readonly "mcpServer/oauth/login": typeof CodexSchema.V2McpServerOauthLoginParams.Type;
176 readonly initialize: CodexSchema.V1InitializeParams;
177 readonly "thread/start": CodexSchema.V2ThreadStartParams;
178 readonly "thread/resume": CodexSchema.V2ThreadResumeParams;
179 readonly "thread/fork": CodexSchema.V2ThreadForkParams;
180 readonly "thread/archive": CodexSchema.V2ThreadArchiveParams;
181 readonly "thread/unsubscribe": CodexSchema.V2ThreadUnsubscribeParams;
182 readonly "thread/name/set": CodexSchema.V2ThreadSetNameParams;
183 readonly "thread/metadata/update": CodexSchema.V2ThreadMetadataUpdateParams;
184 readonly "thread/unarchive": CodexSchema.V2ThreadUnarchiveParams;
185 readonly "thread/compact/start": CodexSchema.V2ThreadCompactStartParams;
186 readonly "thread/shellCommand": CodexSchema.V2ThreadShellCommandParams;
187 readonly "thread/approveGuardianDeniedAction": CodexSchema.V2ThreadApproveGuardianDeniedActionParams;
188 readonly "thread/rollback": CodexSchema.V2ThreadRollbackParams;
189 readonly "thread/list": CodexSchema.V2ThreadListParams;
190 readonly "thread/loaded/list": CodexSchema.V2ThreadLoadedListParams;
191 readonly "thread/read": CodexSchema.V2ThreadReadParams;
192 readonly "thread/inject_items": CodexSchema.V2ThreadInjectItemsParams;
193 readonly "skills/list": CodexSchema.V2SkillsListParams;
194 readonly "hooks/list": CodexSchema.V2HooksListParams;
195 readonly "marketplace/add": CodexSchema.V2MarketplaceAddParams;
196 readonly "marketplace/remove": CodexSchema.V2MarketplaceRemoveParams;
197 readonly "marketplace/upgrade": CodexSchema.V2MarketplaceUpgradeParams;
198 readonly "plugin/list": CodexSchema.V2PluginListParams;
199 readonly "plugin/read": CodexSchema.V2PluginReadParams;
200 readonly "plugin/skill/read": CodexSchema.V2PluginSkillReadParams;
201 readonly "plugin/share/save": CodexSchema.V2PluginShareSaveParams;
202 readonly "plugin/share/updateTargets": CodexSchema.V2PluginShareUpdateTargetsParams;
203 readonly "plugin/share/list": CodexSchema.V2PluginShareListParams;
204 readonly "plugin/share/delete": CodexSchema.V2PluginShareDeleteParams;
205 readonly "app/list": CodexSchema.V2AppsListParams;
206 readonly "fs/readFile": CodexSchema.V2FsReadFileParams;
207 readonly "fs/writeFile": CodexSchema.V2FsWriteFileParams;
208 readonly "fs/createDirectory": CodexSchema.V2FsCreateDirectoryParams;
209 readonly "fs/getMetadata": CodexSchema.V2FsGetMetadataParams;
210 readonly "fs/readDirectory": CodexSchema.V2FsReadDirectoryParams;
211 readonly "fs/remove": CodexSchema.V2FsRemoveParams;
212 readonly "fs/copy": CodexSchema.V2FsCopyParams;
213 readonly "fs/watch": CodexSchema.V2FsWatchParams;
214 readonly "fs/unwatch": CodexSchema.V2FsUnwatchParams;
215 readonly "skills/config/write": CodexSchema.V2SkillsConfigWriteParams;
216 readonly "plugin/install": CodexSchema.V2PluginInstallParams;
217 readonly "plugin/uninstall": CodexSchema.V2PluginUninstallParams;
218 readonly "turn/start": CodexSchema.V2TurnStartParams;
219 readonly "turn/steer": CodexSchema.V2TurnSteerParams;
220 readonly "turn/interrupt": CodexSchema.V2TurnInterruptParams;
221 readonly "review/start": CodexSchema.V2ReviewStartParams;
222 readonly "model/list": CodexSchema.V2ModelListParams;
223 readonly "modelProvider/capabilities/read": CodexSchema.V2ModelProviderCapabilitiesReadParams;
224 readonly "experimentalFeature/list": CodexSchema.V2ExperimentalFeatureListParams;
225 readonly "experimentalFeature/enablement/set": CodexSchema.V2ExperimentalFeatureEnablementSetParams;
226 readonly "mcpServer/oauth/login": CodexSchema.V2McpServerOauthLoginParams;
227227 readonly "config/mcpServer/reload": undefined;
228 readonly "mcpServerStatus/list": typeof CodexSchema.V2ListMcpServerStatusParams.Type;
229 readonly "mcpServer/resource/read": typeof CodexSchema.V2McpResourceReadParams.Type;
230 readonly "mcpServer/tool/call": typeof CodexSchema.V2McpServerToolCallParams.Type;
231 readonly "windowsSandbox/setupStart": typeof CodexSchema.V2WindowsSandboxSetupStartParams.Type;
228 readonly "mcpServerStatus/list": CodexSchema.V2ListMcpServerStatusParams;
229 readonly "mcpServer/resource/read": CodexSchema.V2McpResourceReadParams;
230 readonly "mcpServer/tool/call": CodexSchema.V2McpServerToolCallParams;
231 readonly "windowsSandbox/setupStart": CodexSchema.V2WindowsSandboxSetupStartParams;
232232 readonly "windowsSandbox/readiness": undefined;
233 readonly "account/login/start": typeof CodexSchema.V2LoginAccountParams.Type;
234 readonly "account/login/cancel": typeof CodexSchema.V2CancelLoginAccountParams.Type;
233 readonly "account/login/start": CodexSchema.V2LoginAccountParams;
234 readonly "account/login/cancel": CodexSchema.V2CancelLoginAccountParams;
235235 readonly "account/logout": undefined;
236236 readonly "account/rateLimits/read": undefined;
237 readonly "account/sendAddCreditsNudgeEmail": typeof CodexSchema.V2SendAddCreditsNudgeEmailParams.Type;
238 readonly "feedback/upload": typeof CodexSchema.V2FeedbackUploadParams.Type;
239 readonly "command/exec": typeof CodexSchema.V2CommandExecParams.Type;
240 readonly "command/exec/write": typeof CodexSchema.V2CommandExecWriteParams.Type;
241 readonly "command/exec/terminate": typeof CodexSchema.V2CommandExecTerminateParams.Type;
242 readonly "command/exec/resize": typeof CodexSchema.V2CommandExecResizeParams.Type;
243 readonly "config/read": typeof CodexSchema.V2ConfigReadParams.Type;
244 readonly "externalAgentConfig/detect": typeof CodexSchema.V2ExternalAgentConfigDetectParams.Type;
245 readonly "externalAgentConfig/import": typeof CodexSchema.V2ExternalAgentConfigImportParams.Type;
246 readonly "config/value/write": typeof CodexSchema.V2ConfigValueWriteParams.Type;
247 readonly "config/batchWrite": typeof CodexSchema.V2ConfigBatchWriteParams.Type;
237 readonly "account/sendAddCreditsNudgeEmail": CodexSchema.V2SendAddCreditsNudgeEmailParams;
238 readonly "feedback/upload": CodexSchema.V2FeedbackUploadParams;
239 readonly "command/exec": CodexSchema.V2CommandExecParams;
240 readonly "command/exec/write": CodexSchema.V2CommandExecWriteParams;
241 readonly "command/exec/terminate": CodexSchema.V2CommandExecTerminateParams;
242 readonly "command/exec/resize": CodexSchema.V2CommandExecResizeParams;
243 readonly "config/read": CodexSchema.V2ConfigReadParams;
244 readonly "externalAgentConfig/detect": CodexSchema.V2ExternalAgentConfigDetectParams;
245 readonly "externalAgentConfig/import": CodexSchema.V2ExternalAgentConfigImportParams;
246 readonly "config/value/write": CodexSchema.V2ConfigValueWriteParams;
247 readonly "config/batchWrite": CodexSchema.V2ConfigBatchWriteParams;
248248 readonly "configRequirements/read": undefined;
249 readonly "account/read": typeof CodexSchema.V2GetAccountParams.Type;
250 readonly getConversationSummary: typeof CodexSchema.GetConversationSummaryParams.Type;
251 readonly gitDiffToRemote: typeof CodexSchema.GitDiffToRemoteParams.Type;
252 readonly getAuthStatus: typeof CodexSchema.GetAuthStatusParams.Type;
253 readonly fuzzyFileSearch: typeof CodexSchema.FuzzyFileSearchParams.Type;
249 readonly "account/read": CodexSchema.V2GetAccountParams;
250 readonly getConversationSummary: CodexSchema.GetConversationSummaryParams;
251 readonly gitDiffToRemote: CodexSchema.GitDiffToRemoteParams;
252 readonly getAuthStatus: CodexSchema.GetAuthStatusParams;
253 readonly fuzzyFileSearch: CodexSchema.FuzzyFileSearchParams;
254254}
255255
256256export interface ClientRequestResponsesByMethod {
257 readonly initialize: typeof CodexSchema.V1InitializeResponse.Type;
258 readonly "thread/start": typeof CodexSchema.V2ThreadStartResponse.Type;
259 readonly "thread/resume": typeof CodexSchema.V2ThreadResumeResponse.Type;
260 readonly "thread/fork": typeof CodexSchema.V2ThreadForkResponse.Type;
261 readonly "thread/archive": typeof CodexSchema.V2ThreadArchiveResponse.Type;
262 readonly "thread/unsubscribe": typeof CodexSchema.V2ThreadUnsubscribeResponse.Type;
263 readonly "thread/name/set": typeof CodexSchema.V2ThreadSetNameResponse.Type;
264 readonly "thread/metadata/update": typeof CodexSchema.V2ThreadMetadataUpdateResponse.Type;
265 readonly "thread/unarchive": typeof CodexSchema.V2ThreadUnarchiveResponse.Type;
266 readonly "thread/compact/start": typeof CodexSchema.V2ThreadCompactStartResponse.Type;
267 readonly "thread/shellCommand": typeof CodexSchema.V2ThreadShellCommandResponse.Type;
268 readonly "thread/approveGuardianDeniedAction": typeof CodexSchema.V2ThreadApproveGuardianDeniedActionResponse.Type;
269 readonly "thread/rollback": typeof CodexSchema.V2ThreadRollbackResponse.Type;
270 readonly "thread/list": typeof CodexSchema.V2ThreadListResponse.Type;
271 readonly "thread/loaded/list": typeof CodexSchema.V2ThreadLoadedListResponse.Type;
272 readonly "thread/read": typeof CodexSchema.V2ThreadReadResponse.Type;
273 readonly "thread/inject_items": typeof CodexSchema.V2ThreadInjectItemsResponse.Type;
274 readonly "skills/list": typeof CodexSchema.V2SkillsListResponse.Type;
275 readonly "hooks/list": typeof CodexSchema.V2HooksListResponse.Type;
276 readonly "marketplace/add": typeof CodexSchema.V2MarketplaceAddResponse.Type;
277 readonly "marketplace/remove": typeof CodexSchema.V2MarketplaceRemoveResponse.Type;
278 readonly "marketplace/upgrade": typeof CodexSchema.V2MarketplaceUpgradeResponse.Type;
279 readonly "plugin/list": typeof CodexSchema.V2PluginListResponse.Type;
280 readonly "plugin/read": typeof CodexSchema.V2PluginReadResponse.Type;
281 readonly "plugin/skill/read": typeof CodexSchema.V2PluginSkillReadResponse.Type;
282 readonly "plugin/share/save": typeof CodexSchema.V2PluginShareSaveResponse.Type;
283 readonly "plugin/share/updateTargets": typeof CodexSchema.V2PluginShareUpdateTargetsResponse.Type;
284 readonly "plugin/share/list": typeof CodexSchema.V2PluginShareListResponse.Type;
285 readonly "plugin/share/delete": typeof CodexSchema.V2PluginShareDeleteResponse.Type;
286 readonly "app/list": typeof CodexSchema.V2AppsListResponse.Type;
287 readonly "fs/readFile": typeof CodexSchema.V2FsReadFileResponse.Type;
288 readonly "fs/writeFile": typeof CodexSchema.V2FsWriteFileResponse.Type;
289 readonly "fs/createDirectory": typeof CodexSchema.V2FsCreateDirectoryResponse.Type;
290 readonly "fs/getMetadata": typeof CodexSchema.V2FsGetMetadataResponse.Type;
291 readonly "fs/readDirectory": typeof CodexSchema.V2FsReadDirectoryResponse.Type;
292 readonly "fs/remove": typeof CodexSchema.V2FsRemoveResponse.Type;
293 readonly "fs/copy": typeof CodexSchema.V2FsCopyResponse.Type;
294 readonly "fs/watch": typeof CodexSchema.V2FsWatchResponse.Type;
295 readonly "fs/unwatch": typeof CodexSchema.V2FsUnwatchResponse.Type;
296 readonly "skills/config/write": typeof CodexSchema.V2SkillsConfigWriteResponse.Type;
297 readonly "plugin/install": typeof CodexSchema.V2PluginInstallResponse.Type;
298 readonly "plugin/uninstall": typeof CodexSchema.V2PluginUninstallResponse.Type;
299 readonly "turn/start": typeof CodexSchema.V2TurnStartResponse.Type;
300 readonly "turn/steer": typeof CodexSchema.V2TurnSteerResponse.Type;
301 readonly "turn/interrupt": typeof CodexSchema.V2TurnInterruptResponse.Type;
302 readonly "review/start": typeof CodexSchema.V2ReviewStartResponse.Type;
303 readonly "model/list": typeof CodexSchema.V2ModelListResponse.Type;
304 readonly "modelProvider/capabilities/read": typeof CodexSchema.V2ModelProviderCapabilitiesReadResponse.Type;
305 readonly "experimentalFeature/list": typeof CodexSchema.V2ExperimentalFeatureListResponse.Type;
306 readonly "experimentalFeature/enablement/set": typeof CodexSchema.V2ExperimentalFeatureEnablementSetResponse.Type;
307 readonly "mcpServer/oauth/login": typeof CodexSchema.V2McpServerOauthLoginResponse.Type;
308 readonly "config/mcpServer/reload": typeof CodexSchema.V2McpServerRefreshResponse.Type;
309 readonly "mcpServerStatus/list": typeof CodexSchema.V2ListMcpServerStatusResponse.Type;
310 readonly "mcpServer/resource/read": typeof CodexSchema.V2McpResourceReadResponse.Type;
311 readonly "mcpServer/tool/call": typeof CodexSchema.V2McpServerToolCallResponse.Type;
312 readonly "windowsSandbox/setupStart": typeof CodexSchema.V2WindowsSandboxSetupStartResponse.Type;
313 readonly "windowsSandbox/readiness": typeof CodexSchema.V2WindowsSandboxReadinessResponse.Type;
314 readonly "account/login/start": typeof CodexSchema.V2LoginAccountResponse.Type;
315 readonly "account/login/cancel": typeof CodexSchema.V2CancelLoginAccountResponse.Type;
316 readonly "account/logout": typeof CodexSchema.V2LogoutAccountResponse.Type;
317 readonly "account/rateLimits/read": typeof CodexSchema.V2GetAccountRateLimitsResponse.Type;
318 readonly "account/sendAddCreditsNudgeEmail": typeof CodexSchema.V2SendAddCreditsNudgeEmailResponse.Type;
319 readonly "feedback/upload": typeof CodexSchema.V2FeedbackUploadResponse.Type;
320 readonly "command/exec": typeof CodexSchema.V2CommandExecResponse.Type;
321 readonly "command/exec/write": typeof CodexSchema.V2CommandExecWriteResponse.Type;
322 readonly "command/exec/terminate": typeof CodexSchema.V2CommandExecTerminateResponse.Type;
323 readonly "command/exec/resize": typeof CodexSchema.V2CommandExecResizeResponse.Type;
324 readonly "config/read": typeof CodexSchema.V2ConfigReadResponse.Type;
325 readonly "externalAgentConfig/detect": typeof CodexSchema.V2ExternalAgentConfigDetectResponse.Type;
326 readonly "externalAgentConfig/import": typeof CodexSchema.V2ExternalAgentConfigImportResponse.Type;
327 readonly "config/value/write": typeof CodexSchema.V2ConfigWriteResponse.Type;
328 readonly "config/batchWrite": typeof CodexSchema.V2ConfigWriteResponse.Type;
329 readonly "configRequirements/read": typeof CodexSchema.V2ConfigRequirementsReadResponse.Type;
330 readonly "account/read": typeof CodexSchema.V2GetAccountResponse.Type;
331 readonly getConversationSummary: typeof CodexSchema.GetConversationSummaryResponse.Type;
332 readonly gitDiffToRemote: typeof CodexSchema.GitDiffToRemoteResponse.Type;
333 readonly getAuthStatus: typeof CodexSchema.GetAuthStatusResponse.Type;
334 readonly fuzzyFileSearch: typeof CodexSchema.FuzzyFileSearchResponse.Type;
257 readonly initialize: CodexSchema.V1InitializeResponse;
258 readonly "thread/start": CodexSchema.V2ThreadStartResponse;
259 readonly "thread/resume": CodexSchema.V2ThreadResumeResponse;
260 readonly "thread/fork": CodexSchema.V2ThreadForkResponse;
261 readonly "thread/archive": CodexSchema.V2ThreadArchiveResponse;
262 readonly "thread/unsubscribe": CodexSchema.V2ThreadUnsubscribeResponse;
263 readonly "thread/name/set": CodexSchema.V2ThreadSetNameResponse;
264 readonly "thread/metadata/update": CodexSchema.V2ThreadMetadataUpdateResponse;
265 readonly "thread/unarchive": CodexSchema.V2ThreadUnarchiveResponse;
266 readonly "thread/compact/start": CodexSchema.V2ThreadCompactStartResponse;
267 readonly "thread/shellCommand": CodexSchema.V2ThreadShellCommandResponse;
268 readonly "thread/approveGuardianDeniedAction": CodexSchema.V2ThreadApproveGuardianDeniedActionResponse;
269 readonly "thread/rollback": CodexSchema.V2ThreadRollbackResponse;
270 readonly "thread/list": CodexSchema.V2ThreadListResponse;
271 readonly "thread/loaded/list": CodexSchema.V2ThreadLoadedListResponse;
272 readonly "thread/read": CodexSchema.V2ThreadReadResponse;
273 readonly "thread/inject_items": CodexSchema.V2ThreadInjectItemsResponse;
274 readonly "skills/list": CodexSchema.V2SkillsListResponse;
275 readonly "hooks/list": CodexSchema.V2HooksListResponse;
276 readonly "marketplace/add": CodexSchema.V2MarketplaceAddResponse;
277 readonly "marketplace/remove": CodexSchema.V2MarketplaceRemoveResponse;
278 readonly "marketplace/upgrade": CodexSchema.V2MarketplaceUpgradeResponse;
279 readonly "plugin/list": CodexSchema.V2PluginListResponse;
280 readonly "plugin/read": CodexSchema.V2PluginReadResponse;
281 readonly "plugin/skill/read": CodexSchema.V2PluginSkillReadResponse;
282 readonly "plugin/share/save": CodexSchema.V2PluginShareSaveResponse;
283 readonly "plugin/share/updateTargets": CodexSchema.V2PluginShareUpdateTargetsResponse;
284 readonly "plugin/share/list": CodexSchema.V2PluginShareListResponse;
285 readonly "plugin/share/delete": CodexSchema.V2PluginShareDeleteResponse;
286 readonly "app/list": CodexSchema.V2AppsListResponse;
287 readonly "fs/readFile": CodexSchema.V2FsReadFileResponse;
288 readonly "fs/writeFile": CodexSchema.V2FsWriteFileResponse;
289 readonly "fs/createDirectory": CodexSchema.V2FsCreateDirectoryResponse;
290 readonly "fs/getMetadata": CodexSchema.V2FsGetMetadataResponse;
291 readonly "fs/readDirectory": CodexSchema.V2FsReadDirectoryResponse;
292 readonly "fs/remove": CodexSchema.V2FsRemoveResponse;
293 readonly "fs/copy": CodexSchema.V2FsCopyResponse;
294 readonly "fs/watch": CodexSchema.V2FsWatchResponse;
295 readonly "fs/unwatch": CodexSchema.V2FsUnwatchResponse;
296 readonly "skills/config/write": CodexSchema.V2SkillsConfigWriteResponse;
297 readonly "plugin/install": CodexSchema.V2PluginInstallResponse;
298 readonly "plugin/uninstall": CodexSchema.V2PluginUninstallResponse;
299 readonly "turn/start": CodexSchema.V2TurnStartResponse;
300 readonly "turn/steer": CodexSchema.V2TurnSteerResponse;
301 readonly "turn/interrupt": CodexSchema.V2TurnInterruptResponse;
302 readonly "review/start": CodexSchema.V2ReviewStartResponse;
303 readonly "model/list": CodexSchema.V2ModelListResponse;
304 readonly "modelProvider/capabilities/read": CodexSchema.V2ModelProviderCapabilitiesReadResponse;
305 readonly "experimentalFeature/list": CodexSchema.V2ExperimentalFeatureListResponse;
306 readonly "experimentalFeature/enablement/set": CodexSchema.V2ExperimentalFeatureEnablementSetResponse;
307 readonly "mcpServer/oauth/login": CodexSchema.V2McpServerOauthLoginResponse;
308 readonly "config/mcpServer/reload": CodexSchema.V2McpServerRefreshResponse;
309 readonly "mcpServerStatus/list": CodexSchema.V2ListMcpServerStatusResponse;
310 readonly "mcpServer/resource/read": CodexSchema.V2McpResourceReadResponse;
311 readonly "mcpServer/tool/call": CodexSchema.V2McpServerToolCallResponse;
312 readonly "windowsSandbox/setupStart": CodexSchema.V2WindowsSandboxSetupStartResponse;
313 readonly "windowsSandbox/readiness": CodexSchema.V2WindowsSandboxReadinessResponse;
314 readonly "account/login/start": CodexSchema.V2LoginAccountResponse;
315 readonly "account/login/cancel": CodexSchema.V2CancelLoginAccountResponse;
316 readonly "account/logout": CodexSchema.V2LogoutAccountResponse;
317 readonly "account/rateLimits/read": CodexSchema.V2GetAccountRateLimitsResponse;
318 readonly "account/sendAddCreditsNudgeEmail": CodexSchema.V2SendAddCreditsNudgeEmailResponse;
319 readonly "feedback/upload": CodexSchema.V2FeedbackUploadResponse;
320 readonly "command/exec": CodexSchema.V2CommandExecResponse;
321 readonly "command/exec/write": CodexSchema.V2CommandExecWriteResponse;
322 readonly "command/exec/terminate": CodexSchema.V2CommandExecTerminateResponse;
323 readonly "command/exec/resize": CodexSchema.V2CommandExecResizeResponse;
324 readonly "config/read": CodexSchema.V2ConfigReadResponse;
325 readonly "externalAgentConfig/detect": CodexSchema.V2ExternalAgentConfigDetectResponse;
326 readonly "externalAgentConfig/import": CodexSchema.V2ExternalAgentConfigImportResponse;
327 readonly "config/value/write": CodexSchema.V2ConfigWriteResponse;
328 readonly "config/batchWrite": CodexSchema.V2ConfigWriteResponse;
329 readonly "configRequirements/read": CodexSchema.V2ConfigRequirementsReadResponse;
330 readonly "account/read": CodexSchema.V2GetAccountResponse;
331 readonly getConversationSummary: CodexSchema.GetConversationSummaryResponse;
332 readonly gitDiffToRemote: CodexSchema.GitDiffToRemoteResponse;
333 readonly getAuthStatus: CodexSchema.GetAuthStatusResponse;
334 readonly fuzzyFileSearch: CodexSchema.FuzzyFileSearchResponse;
335335}
336336
337337export interface ClientNotificationParamsByMethod {
......@@ -339,94 +339,94 @@ export interface ClientNotificationParamsByMethod {
339339}
340340
341341export interface ServerRequestParamsByMethod {
342 readonly "item/commandExecution/requestApproval": typeof CodexSchema.CommandExecutionRequestApprovalParams.Type;
343 readonly "item/fileChange/requestApproval": typeof CodexSchema.FileChangeRequestApprovalParams.Type;
344 readonly "item/tool/requestUserInput": typeof CodexSchema.ToolRequestUserInputParams.Type;
345 readonly "mcpServer/elicitation/request": typeof CodexSchema.McpServerElicitationRequestParams.Type;
346 readonly "item/permissions/requestApproval": typeof CodexSchema.PermissionsRequestApprovalParams.Type;
347 readonly "item/tool/call": typeof CodexSchema.DynamicToolCallParams.Type;
348 readonly "account/chatgptAuthTokens/refresh": typeof CodexSchema.ChatgptAuthTokensRefreshParams.Type;
349 readonly applyPatchApproval: typeof CodexSchema.ApplyPatchApprovalParams.Type;
350 readonly execCommandApproval: typeof CodexSchema.ExecCommandApprovalParams.Type;
342 readonly "item/commandExecution/requestApproval": CodexSchema.CommandExecutionRequestApprovalParams;
343 readonly "item/fileChange/requestApproval": CodexSchema.FileChangeRequestApprovalParams;
344 readonly "item/tool/requestUserInput": CodexSchema.ToolRequestUserInputParams;
345 readonly "mcpServer/elicitation/request": CodexSchema.McpServerElicitationRequestParams;
346 readonly "item/permissions/requestApproval": CodexSchema.PermissionsRequestApprovalParams;
347 readonly "item/tool/call": CodexSchema.DynamicToolCallParams;
348 readonly "account/chatgptAuthTokens/refresh": CodexSchema.ChatgptAuthTokensRefreshParams;
349 readonly applyPatchApproval: CodexSchema.ApplyPatchApprovalParams;
350 readonly execCommandApproval: CodexSchema.ExecCommandApprovalParams;
351351}
352352
353353export interface ServerRequestResponsesByMethod {
354 readonly "item/commandExecution/requestApproval": typeof CodexSchema.CommandExecutionRequestApprovalResponse.Type;
355 readonly "item/fileChange/requestApproval": typeof CodexSchema.FileChangeRequestApprovalResponse.Type;
356 readonly "item/tool/requestUserInput": typeof CodexSchema.ToolRequestUserInputResponse.Type;
357 readonly "mcpServer/elicitation/request": typeof CodexSchema.McpServerElicitationRequestResponse.Type;
358 readonly "item/permissions/requestApproval": typeof CodexSchema.PermissionsRequestApprovalResponse.Type;
359 readonly "item/tool/call": typeof CodexSchema.DynamicToolCallResponse.Type;
360 readonly "account/chatgptAuthTokens/refresh": typeof CodexSchema.ChatgptAuthTokensRefreshResponse.Type;
361 readonly applyPatchApproval: typeof CodexSchema.ApplyPatchApprovalResponse.Type;
362 readonly execCommandApproval: typeof CodexSchema.ExecCommandApprovalResponse.Type;
354 readonly "item/commandExecution/requestApproval": CodexSchema.CommandExecutionRequestApprovalResponse;
355 readonly "item/fileChange/requestApproval": CodexSchema.FileChangeRequestApprovalResponse;
356 readonly "item/tool/requestUserInput": CodexSchema.ToolRequestUserInputResponse;
357 readonly "mcpServer/elicitation/request": CodexSchema.McpServerElicitationRequestResponse;
358 readonly "item/permissions/requestApproval": CodexSchema.PermissionsRequestApprovalResponse;
359 readonly "item/tool/call": CodexSchema.DynamicToolCallResponse;
360 readonly "account/chatgptAuthTokens/refresh": CodexSchema.ChatgptAuthTokensRefreshResponse;
361 readonly applyPatchApproval: CodexSchema.ApplyPatchApprovalResponse;
362 readonly execCommandApproval: CodexSchema.ExecCommandApprovalResponse;
363363}
364364
365365export interface ServerNotificationParamsByMethod {
366 readonly error: typeof CodexSchema.V2ErrorNotification.Type;
367 readonly "thread/started": typeof CodexSchema.V2ThreadStartedNotification.Type;
368 readonly "thread/status/changed": typeof CodexSchema.V2ThreadStatusChangedNotification.Type;
369 readonly "thread/archived": typeof CodexSchema.V2ThreadArchivedNotification.Type;
370 readonly "thread/unarchived": typeof CodexSchema.V2ThreadUnarchivedNotification.Type;
371 readonly "thread/closed": typeof CodexSchema.V2ThreadClosedNotification.Type;
372 readonly "skills/changed": typeof CodexSchema.V2SkillsChangedNotification.Type;
373 readonly "thread/name/updated": typeof CodexSchema.V2ThreadNameUpdatedNotification.Type;
374 readonly "thread/goal/updated": typeof CodexSchema.V2ThreadGoalUpdatedNotification.Type;
375 readonly "thread/goal/cleared": typeof CodexSchema.V2ThreadGoalClearedNotification.Type;
376 readonly "thread/tokenUsage/updated": typeof CodexSchema.V2ThreadTokenUsageUpdatedNotification.Type;
377 readonly "turn/started": typeof CodexSchema.V2TurnStartedNotification.Type;
378 readonly "hook/started": typeof CodexSchema.V2HookStartedNotification.Type;
379 readonly "turn/completed": typeof CodexSchema.V2TurnCompletedNotification.Type;
380 readonly "hook/completed": typeof CodexSchema.V2HookCompletedNotification.Type;
381 readonly "turn/diff/updated": typeof CodexSchema.V2TurnDiffUpdatedNotification.Type;
382 readonly "turn/plan/updated": typeof CodexSchema.V2TurnPlanUpdatedNotification.Type;
383 readonly "item/started": typeof CodexSchema.V2ItemStartedNotification.Type;
384 readonly "item/autoApprovalReview/started": typeof CodexSchema.V2ItemGuardianApprovalReviewStartedNotification.Type;
385 readonly "item/autoApprovalReview/completed": typeof CodexSchema.V2ItemGuardianApprovalReviewCompletedNotification.Type;
386 readonly "item/completed": typeof CodexSchema.V2ItemCompletedNotification.Type;
387 readonly "rawResponseItem/completed": typeof CodexSchema.V2RawResponseItemCompletedNotification.Type;
388 readonly "item/agentMessage/delta": typeof CodexSchema.V2AgentMessageDeltaNotification.Type;
389 readonly "item/plan/delta": typeof CodexSchema.V2PlanDeltaNotification.Type;
390 readonly "command/exec/outputDelta": typeof CodexSchema.V2CommandExecOutputDeltaNotification.Type;
391 readonly "process/outputDelta": typeof CodexSchema.V2ProcessOutputDeltaNotification.Type;
392 readonly "process/exited": typeof CodexSchema.V2ProcessExitedNotification.Type;
393 readonly "item/commandExecution/outputDelta": typeof CodexSchema.V2CommandExecutionOutputDeltaNotification.Type;
394 readonly "item/commandExecution/terminalInteraction": typeof CodexSchema.V2TerminalInteractionNotification.Type;
395 readonly "item/fileChange/outputDelta": typeof CodexSchema.V2FileChangeOutputDeltaNotification.Type;
396 readonly "item/fileChange/patchUpdated": typeof CodexSchema.V2FileChangePatchUpdatedNotification.Type;
397 readonly "serverRequest/resolved": typeof CodexSchema.V2ServerRequestResolvedNotification.Type;
398 readonly "item/mcpToolCall/progress": typeof CodexSchema.V2McpToolCallProgressNotification.Type;
399 readonly "mcpServer/oauthLogin/completed": typeof CodexSchema.V2McpServerOauthLoginCompletedNotification.Type;
400 readonly "mcpServer/startupStatus/updated": typeof CodexSchema.V2McpServerStatusUpdatedNotification.Type;
401 readonly "account/updated": typeof CodexSchema.V2AccountUpdatedNotification.Type;
402 readonly "account/rateLimits/updated": typeof CodexSchema.V2AccountRateLimitsUpdatedNotification.Type;
403 readonly "app/list/updated": typeof CodexSchema.V2AppListUpdatedNotification.Type;
404 readonly "remoteControl/status/changed": typeof CodexSchema.V2RemoteControlStatusChangedNotification.Type;
405 readonly "externalAgentConfig/import/completed": typeof CodexSchema.V2ExternalAgentConfigImportCompletedNotification.Type;
406 readonly "fs/changed": typeof CodexSchema.V2FsChangedNotification.Type;
407 readonly "item/reasoning/summaryTextDelta": typeof CodexSchema.V2ReasoningSummaryTextDeltaNotification.Type;
408 readonly "item/reasoning/summaryPartAdded": typeof CodexSchema.V2ReasoningSummaryPartAddedNotification.Type;
409 readonly "item/reasoning/textDelta": typeof CodexSchema.V2ReasoningTextDeltaNotification.Type;
410 readonly "thread/compacted": typeof CodexSchema.V2ContextCompactedNotification.Type;
411 readonly "model/rerouted": typeof CodexSchema.V2ModelReroutedNotification.Type;
412 readonly "model/verification": typeof CodexSchema.V2ModelVerificationNotification.Type;
413 readonly warning: typeof CodexSchema.V2WarningNotification.Type;
414 readonly guardianWarning: typeof CodexSchema.V2GuardianWarningNotification.Type;
415 readonly deprecationNotice: typeof CodexSchema.V2DeprecationNoticeNotification.Type;
416 readonly configWarning: typeof CodexSchema.V2ConfigWarningNotification.Type;
417 readonly "fuzzyFileSearch/sessionUpdated": typeof CodexSchema.FuzzyFileSearchSessionUpdatedNotification.Type;
418 readonly "fuzzyFileSearch/sessionCompleted": typeof CodexSchema.FuzzyFileSearchSessionCompletedNotification.Type;
419 readonly "thread/realtime/started": typeof CodexSchema.V2ThreadRealtimeStartedNotification.Type;
420 readonly "thread/realtime/itemAdded": typeof CodexSchema.V2ThreadRealtimeItemAddedNotification.Type;
421 readonly "thread/realtime/transcript/delta": typeof CodexSchema.V2ThreadRealtimeTranscriptDeltaNotification.Type;
422 readonly "thread/realtime/transcript/done": typeof CodexSchema.V2ThreadRealtimeTranscriptDoneNotification.Type;
423 readonly "thread/realtime/outputAudio/delta": typeof CodexSchema.V2ThreadRealtimeOutputAudioDeltaNotification.Type;
424 readonly "thread/realtime/sdp": typeof CodexSchema.V2ThreadRealtimeSdpNotification.Type;
425 readonly "thread/realtime/error": typeof CodexSchema.V2ThreadRealtimeErrorNotification.Type;
426 readonly "thread/realtime/closed": typeof CodexSchema.V2ThreadRealtimeClosedNotification.Type;
427 readonly "windows/worldWritableWarning": typeof CodexSchema.V2WindowsWorldWritableWarningNotification.Type;
428 readonly "windowsSandbox/setupCompleted": typeof CodexSchema.V2WindowsSandboxSetupCompletedNotification.Type;
429 readonly "account/login/completed": typeof CodexSchema.V2AccountLoginCompletedNotification.Type;
366 readonly error: CodexSchema.V2ErrorNotification;
367 readonly "thread/started": CodexSchema.V2ThreadStartedNotification;
368 readonly "thread/status/changed": CodexSchema.V2ThreadStatusChangedNotification;
369 readonly "thread/archived": CodexSchema.V2ThreadArchivedNotification;
370 readonly "thread/unarchived": CodexSchema.V2ThreadUnarchivedNotification;
371 readonly "thread/closed": CodexSchema.V2ThreadClosedNotification;
372 readonly "skills/changed": CodexSchema.V2SkillsChangedNotification;
373 readonly "thread/name/updated": CodexSchema.V2ThreadNameUpdatedNotification;
374 readonly "thread/goal/updated": CodexSchema.V2ThreadGoalUpdatedNotification;
375 readonly "thread/goal/cleared": CodexSchema.V2ThreadGoalClearedNotification;
376 readonly "thread/tokenUsage/updated": CodexSchema.V2ThreadTokenUsageUpdatedNotification;
377 readonly "turn/started": CodexSchema.V2TurnStartedNotification;
378 readonly "hook/started": CodexSchema.V2HookStartedNotification;
379 readonly "turn/completed": CodexSchema.V2TurnCompletedNotification;
380 readonly "hook/completed": CodexSchema.V2HookCompletedNotification;
381 readonly "turn/diff/updated": CodexSchema.V2TurnDiffUpdatedNotification;
382 readonly "turn/plan/updated": CodexSchema.V2TurnPlanUpdatedNotification;
383 readonly "item/started": CodexSchema.V2ItemStartedNotification;
384 readonly "item/autoApprovalReview/started": CodexSchema.V2ItemGuardianApprovalReviewStartedNotification;
385 readonly "item/autoApprovalReview/completed": CodexSchema.V2ItemGuardianApprovalReviewCompletedNotification;
386 readonly "item/completed": CodexSchema.V2ItemCompletedNotification;
387 readonly "rawResponseItem/completed": CodexSchema.V2RawResponseItemCompletedNotification;
388 readonly "item/agentMessage/delta": CodexSchema.V2AgentMessageDeltaNotification;
389 readonly "item/plan/delta": CodexSchema.V2PlanDeltaNotification;
390 readonly "command/exec/outputDelta": CodexSchema.V2CommandExecOutputDeltaNotification;
391 readonly "process/outputDelta": CodexSchema.V2ProcessOutputDeltaNotification;
392 readonly "process/exited": CodexSchema.V2ProcessExitedNotification;
393 readonly "item/commandExecution/outputDelta": CodexSchema.V2CommandExecutionOutputDeltaNotification;
394 readonly "item/commandExecution/terminalInteraction": CodexSchema.V2TerminalInteractionNotification;
395 readonly "item/fileChange/outputDelta": CodexSchema.V2FileChangeOutputDeltaNotification;
396 readonly "item/fileChange/patchUpdated": CodexSchema.V2FileChangePatchUpdatedNotification;
397 readonly "serverRequest/resolved": CodexSchema.V2ServerRequestResolvedNotification;
398 readonly "item/mcpToolCall/progress": CodexSchema.V2McpToolCallProgressNotification;
399 readonly "mcpServer/oauthLogin/completed": CodexSchema.V2McpServerOauthLoginCompletedNotification;
400 readonly "mcpServer/startupStatus/updated": CodexSchema.V2McpServerStatusUpdatedNotification;
401 readonly "account/updated": CodexSchema.V2AccountUpdatedNotification;
402 readonly "account/rateLimits/updated": CodexSchema.V2AccountRateLimitsUpdatedNotification;
403 readonly "app/list/updated": CodexSchema.V2AppListUpdatedNotification;
404 readonly "remoteControl/status/changed": CodexSchema.V2RemoteControlStatusChangedNotification;
405 readonly "externalAgentConfig/import/completed": CodexSchema.V2ExternalAgentConfigImportCompletedNotification;
406 readonly "fs/changed": CodexSchema.V2FsChangedNotification;
407 readonly "item/reasoning/summaryTextDelta": CodexSchema.V2ReasoningSummaryTextDeltaNotification;
408 readonly "item/reasoning/summaryPartAdded": CodexSchema.V2ReasoningSummaryPartAddedNotification;
409 readonly "item/reasoning/textDelta": CodexSchema.V2ReasoningTextDeltaNotification;
410 readonly "thread/compacted": CodexSchema.V2ContextCompactedNotification;
411 readonly "model/rerouted": CodexSchema.V2ModelReroutedNotification;
412 readonly "model/verification": CodexSchema.V2ModelVerificationNotification;
413 readonly warning: CodexSchema.V2WarningNotification;
414 readonly guardianWarning: CodexSchema.V2GuardianWarningNotification;
415 readonly deprecationNotice: CodexSchema.V2DeprecationNoticeNotification;
416 readonly configWarning: CodexSchema.V2ConfigWarningNotification;
417 readonly "fuzzyFileSearch/sessionUpdated": CodexSchema.FuzzyFileSearchSessionUpdatedNotification;
418 readonly "fuzzyFileSearch/sessionCompleted": CodexSchema.FuzzyFileSearchSessionCompletedNotification;
419 readonly "thread/realtime/started": CodexSchema.V2ThreadRealtimeStartedNotification;
420 readonly "thread/realtime/itemAdded": CodexSchema.V2ThreadRealtimeItemAddedNotification;
421 readonly "thread/realtime/transcript/delta": CodexSchema.V2ThreadRealtimeTranscriptDeltaNotification;
422 readonly "thread/realtime/transcript/done": CodexSchema.V2ThreadRealtimeTranscriptDoneNotification;
423 readonly "thread/realtime/outputAudio/delta": CodexSchema.V2ThreadRealtimeOutputAudioDeltaNotification;
424 readonly "thread/realtime/sdp": CodexSchema.V2ThreadRealtimeSdpNotification;
425 readonly "thread/realtime/error": CodexSchema.V2ThreadRealtimeErrorNotification;
426 readonly "thread/realtime/closed": CodexSchema.V2ThreadRealtimeClosedNotification;
427 readonly "windows/worldWritableWarning": CodexSchema.V2WindowsWorldWritableWarningNotification;
428 readonly "windowsSandbox/setupCompleted": CodexSchema.V2WindowsSandboxSetupCompletedNotification;
429 readonly "account/login/completed": CodexSchema.V2AccountLoginCompletedNotification;
430430}
431431
432432export const CLIENT_REQUEST_PARAMS = {
packages/effect-codex-app-server/src/client.ts+1-1
......@@ -75,7 +75,7 @@ export interface CodexAppServerClientShape {
7575export class CodexAppServerClient extends Context.Service<
7676 CodexAppServerClient,
7777 CodexAppServerClientShape
78>()("effect-codex-app-server/CodexAppServerClient") {}
78>()("effect-codex-app-server/client/CodexAppServerClient") {}
7979
8080type ServerRequestHandler = (
8181 payload: unknown,
packages/effect-codex-app-server/tsconfig.json+3-1
......@@ -1,5 +1,7 @@
11{
22 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},
3 "compilerOptions": {
4 "types": ["node"]
5 },
46 "include": ["src", "scripts", "test"]
57}
packages/shared/package.json+1-3
......@@ -93,7 +93,7 @@
9393 }
9494 },
9595 "scripts": {
96 "typecheck": "tsc --noEmit",
96 "typecheck": "tsgo --noEmit",
9797 "test": "vitest run"
9898 },
9999 "dependencies": {
......@@ -101,11 +101,9 @@
101101 "effect": "catalog:"
102102 },
103103 "devDependencies": {
104 "@effect/language-service": "catalog:",
105104 "@effect/platform-node": "catalog:",
106105 "@effect/vitest": "catalog:",
107106 "@types/node": "catalog:",
108 "typescript": "catalog:",
109107 "vitest": "catalog:"
110108 }
111109}
packages/shared/src/schemaJson.test.ts+21-1
......@@ -1,6 +1,9 @@
1import * as Schema from "effect/Schema";
12import { 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
58describe("schemaJson helpers", () => {
69 it("extracts a balanced JSON object from surrounding text", () => {
......@@ -28,4 +31,21 @@ Done.`),
2831 it("returns trimmed input when no JSON object starts", () => {
2932 expect(extractJsonObject(" no structured output ")).toBe("no structured output");
3033 });
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 });
3151});
packages/shared/src/schemaJson.ts+26-25
......@@ -45,32 +45,33 @@ export const formatSchemaError = (cause: Cause.Cause<Schema.SchemaError>) => {
4545 * A `Getter` that parses a lenient JSON string (tolerating trailing commas
4646 * and JS-style comments) into an unknown value.
4747 *
48 * Mirrors `SchemaGetter.parseJson()` but uses `parseLenientJson` instead
49 * of `JSON.parse`.
48 * Mirrors `SchemaGetter.parseJson()` but strips JSONC syntax before parsing.
5049 */
51const parseLenientJsonGetter = SchemaGetter.onSome((input: string) =>
52 Effect.try({
53 try: () => {
54 // Strip single-line comments — alternation preserves quoted strings.
55 let stripped = input.replace(
56 /("(?:[^"\\]|\\.)*")|\/\/[^\n]*/g,
57 (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""),
58 );
59
60 // Strip multi-line comments.
61 stripped = stripped.replace(
62 /("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g,
63 (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""),
64 );
65
66 // Strip trailing commas before `}` or `]`.
67 stripped = stripped.replace(/,(\s*[}\]])/g, "$1");
68
69 return Option.some(JSON.parse(stripped));
70 },
71 catch: (e) => new SchemaIssue.InvalidValue(Option.some(input), { message: String(e) }),
72 }),
73);
50const decodeJsonString = Schema.decodeEffect(Schema.UnknownFromJsonString);
51
52const parseLenientJsonGetter = SchemaGetter.onSome((input: string) => {
53 // Strip single-line comments - alternation preserves quoted strings.
54 let stripped = input.replace(
55 /("(?:[^"\\]|\\.)*")|\/\/[^\n]*/g,
56 (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""),
57 );
58
59 // Strip multi-line comments.
60 stripped = stripped.replace(
61 /("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g,
62 (match, stringLiteral: string | undefined) => (stringLiteral ? match : ""),
63 );
64
65 // Strip trailing commas before `}` or `]`.
66 stripped = stripped.replace(/,(\s*[}\]])/g, "$1");
67
68 return decodeJsonString(stripped).pipe(
69 Effect.map(Option.some),
70 Effect.mapError(
71 (error) => new SchemaIssue.InvalidValue(Option.some(input), { message: String(error) }),
72 ),
73 );
74});
7475
7576/**
7677 * Schema transformation: lenient JSONC string ↔ unknown.
packages/shared/tsconfig.json+3-1
......@@ -1,5 +1,7 @@
11{
22 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},
3 "compilerOptions": {
4 "types": ["node"]
5 },
46 "include": ["src"]
57}
packages/ssh/package.json+1-3
......@@ -25,7 +25,7 @@
2525 }
2626 },
2727 "scripts": {
28 "typecheck": "tsc --noEmit",
28 "typecheck": "tsgo --noEmit",
2929 "test": "vitest run"
3030 },
3131 "dependencies": {
......@@ -34,11 +34,9 @@
3434 "effect": "catalog:"
3535 },
3636 "devDependencies": {
37 "@effect/language-service": "catalog:",
3837 "@effect/platform-node": "catalog:",
3938 "@effect/vitest": "catalog:",
4039 "@types/node": "catalog:",
41 "typescript": "catalog:",
4240 "vitest": "catalog:"
4341 }
4442}
packages/ssh/src/auth.ts+1-1
......@@ -39,7 +39,7 @@ export interface SshPasswordPromptShape {
3939}
4040
4141export class SshPasswordPrompt extends Context.Service<SshPasswordPrompt, SshPasswordPromptShape>()(
42 "@t3tools/ssh/SshPasswordPrompt",
42 "@t3tools/ssh/auth/SshPasswordPrompt",
4343) {
4444 static readonly disabledLayer = Layer.succeed(
4545 SshPasswordPrompt,
packages/ssh/src/tunnel.ts+4-1
......@@ -1753,10 +1753,13 @@ const makeSshEnvironmentManager = Effect.fn("ssh/tunnel.SshEnvironmentManager.ma
17531753 return SshEnvironmentManager.of({ ensureEnvironment, disconnectEnvironment });
17541754});
17551755
1756/**
1757 * @effect-expect-leaking ChildProcessSpawner | FileSystem | HttpClient | NetService | Path | SshPasswordPrompt
1758 */
17561759export class SshEnvironmentManager extends Context.Service<
17571760 SshEnvironmentManager,
17581761 SshEnvironmentManagerShape
1759>()("@t3tools/ssh/SshEnvironmentManager") {
1762>()("@t3tools/ssh/tunnel/SshEnvironmentManager") {
17601763 static readonly layer = (options: SshEnvironmentManagerOptions = {}) =>
17611764 Layer.effect(SshEnvironmentManager, makeSshEnvironmentManager(options));
17621765}
packages/ssh/tsconfig.json+3-1
......@@ -1,5 +1,7 @@
11{
22 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},
3 "compilerOptions": {
4 "types": ["node"]
5 },
46 "include": ["src"]
57}
packages/tailscale/package.json+1-3
......@@ -9,7 +9,7 @@
99 }
1010 },
1111 "scripts": {
12 "typecheck": "tsc --noEmit",
12 "typecheck": "tsgo --noEmit",
1313 "test": "vitest run"
1414 },
1515 "dependencies": {
......@@ -17,10 +17,8 @@
1717 "effect": "catalog:"
1818 },
1919 "devDependencies": {
20 "@effect/language-service": "catalog:",
2120 "@effect/vitest": "catalog:",
2221 "@types/node": "catalog:",
23 "typescript": "catalog:",
2422 "vitest": "catalog:"
2523 }
2624}
packages/tailscale/tsconfig.json+3-1
......@@ -1,5 +1,7 @@
11{
22 "extends": "../../tsconfig.base.json",
3 "compilerOptions": {},
3 "compilerOptions": {
4 "types": ["node"]
5 },
46 "include": ["src"]
57}
scripts/package.json+1-3
......@@ -3,7 +3,7 @@
33 "private": true,
44 "type": "module",
55 "scripts": {
6 "typecheck": "tsc --noEmit",
6 "typecheck": "tsgo --noEmit",
77 "test": "vitest run"
88 },
99 "dependencies": {
......@@ -14,10 +14,8 @@
1414 "effect": "catalog:"
1515 },
1616 "devDependencies": {
17 "@effect/language-service": "catalog:",
1817 "@effect/vitest": "catalog:",
1918 "@types/bun": "catalog:",
20 "typescript": "catalog:",
2119 "vitest": "catalog:"
2220 }
2321}
tsconfig.base.json+4-1
......@@ -35,6 +35,7 @@
3535 "globalErrorInEffectFailure": "error",
3636 "unknownInEffectCatch": "error",
3737 "strictBooleanExpressions": "off",
38 "lazyEffect": "off",
3839 "preferSchemaOverJson": "error",
3940 "schemaSyncInEffect": "error",
4041 "cryptoRandomUUID": "error",
......@@ -47,7 +48,9 @@
4748 "globalRandom": "error",
4849 "globalRandomInEffect": "error",
4950 "globalTimers": "error",
50 "globalTimersInEffect": "error"
51 "globalTimersInEffect": "error",
52 "globalFetch": "error",
53 "globalFetchInEffect": "error"
5154 }
5255 }
5356 ]