1282 lines · 48.5 KB · TypeScript
RawDownload
import * as NodeServices from "@effect/platform-node/NodeServices";import {  DEFAULT_SERVER_SETTINGS,  ProviderDriverKind,  ProviderInstanceId,  resolveProviderInstanceEnabled,  ServerSettings,  ServerSettingsPatch,} from "@t3tools/contracts";import { createModelSelection } from "@t3tools/shared/model";import { assert, it } from "@effect/vitest";import * as Effect from "effect/Effect";import * as Duration from "effect/Duration";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Path from "effect/Path";import * as PlatformError from "effect/PlatformError";import * as Schema from "effect/Schema";import * as Stream from "effect/Stream";import * as SqlClient from "effect/unstable/sql/SqlClient";import * as ServerSecretStore from "./auth/ServerSecretStore.ts";import * as ServerConfig from "./config.ts";import { SqlitePersistenceMemory } from "./persistence/Layers/Sqlite.ts";import * as ServerSettingsModule from "./serverSettings.ts";import { resolveProviderInstanceTerminalEnvironment } from "./terminal/Manager.ts"; const decodeSettingsPatch = Schema.decodeUnknownEffect(ServerSettingsPatch);const decodeServerSettings = Schema.decodeUnknownEffect(ServerSettings); const makeServerSettingsLayer = () =>  ServerSettingsModule.layer.pipe(    Layer.provide(ServerSecretStore.layer),    Layer.provideMerge(Layer.fresh(SqlitePersistenceMemory)),    Layer.provideMerge(      Layer.fresh(        ServerConfig.layerTest(process.cwd(), {          prefix: "t3code-server-settings-test-",        }),      ),    ),  ); const makeFailingSecretStoreLayer = (cause: ServerSecretStore.SecretStoreError) =>  Layer.succeed(    ServerSecretStore.ServerSecretStore,    ServerSecretStore.ServerSecretStore.of({      get: () => Effect.fail(cause),      set: () => Effect.void,      create: () => Effect.void,      getOrCreateRandom: () => Effect.succeed(new Uint8Array()),      remove: () => Effect.void,    }),  ); const recordProviderUsage = (provider: string, instanceId: string | null = provider) =>  Effect.gen(function* () {    const sql = yield* SqlClient.SqlClient;    yield* sql`      INSERT INTO projection_thread_sessions (        thread_id,        status,        provider_name,        provider_instance_id,        updated_at      )      VALUES (        ${`thread-${instanceId ?? provider}`},        ${"ready"},        ${provider},        ${instanceId},        ${"2026-08-25T00:00:00.000Z"}      )    `;  }); it.layer(NodeServices.layer)("server settings", (it) => {  it.effect("preserves context when reading a provider environment secret fails", () => {    const platformCause = PlatformError.systemError({      _tag: "PermissionDenied",      module: "FileSystem",      method: "readFile",      pathOrDescriptor: "provider environment secret",      description: "Secret backend unavailable.",    });    const cause = new ServerSecretStore.SecretStoreReadError({      resource: "provider environment secret",      cause: platformCause,    });    const configLayer = Layer.fresh(      ServerConfig.layerTest(process.cwd(), {        prefix: "t3code-server-settings-secret-failure-test-",      }),    );    const settingsLayer = ServerSettingsModule.layer.pipe(      Layer.provide(makeFailingSecretStoreLayer(cause)),      Layer.provideMerge(Layer.fresh(SqlitePersistenceMemory)),      Layer.provideMerge(configLayer),    );     return Effect.gen(function* () {      const serverConfig = yield* ServerConfig.ServerConfig;      const fileSystem = yield* FileSystem.FileSystem;      const serverSettings = yield* ServerSettingsModule.ServerSettingsService;      yield* fileSystem.writeFileString(        serverConfig.settingsPath,        '{"providerInstances":{"codex_personal":{"driver":"codex","environment":[{"name":"OPENROUTER_API_KEY","value":"","sensitive":true,"valueRedacted":true}],"config":{}}}}',      );       const error = yield* Effect.flip(serverSettings.getSettings);       assert.deepInclude(error, {        _tag: "ServerSettingsError",        operation: "read-secret",        providerInstanceId: "codex_personal",        environmentVariable: "OPENROUTER_API_KEY",      });      assert.strictEqual(error.cause, cause);      assert.notInclude(error.message, cause.message);    }).pipe(Effect.provide(settingsLayer));  });   it.effect("identifies provider history query failures", () =>    Effect.gen(function* () {      const serverConfig = yield* ServerConfig.ServerConfig;      const serverSettings = yield* ServerSettingsModule.ServerSettingsService;      const sql = yield* SqlClient.SqlClient;      yield* sql`DROP TABLE projection_thread_sessions`;       const error = yield* Effect.flip(serverSettings.getSettings);       assert.deepInclude(error, {        _tag: "ServerSettingsError",        operation: "read-provider-history",        settingsPath: serverConfig.settingsPath,      });    }).pipe(Effect.provide(makeServerSettingsLayer())),  );   it.effect("decodes nested settings patches", () =>    Effect.gen(function* () {      assert.deepEqual(        yield* decodeSettingsPatch({ providers: { codex: { binaryPath: "/tmp/codex" } } }),        {          providers: { codex: { binaryPath: "/tmp/codex" } },        },      );       assert.deepEqual(        yield* decodeSettingsPatch({          textGenerationModelSelection: {            options: [{ id: "fastMode", value: false }],          },        }),        {          textGenerationModelSelection: {            options: [{ id: "fastMode", value: false }],          },        },      );    }),  );   it.effect(    "decodes legacy object-shaped textGenerationModelSelection.options from settings.json",    () =>      Effect.gen(function* () {        const decoded = yield* decodeServerSettings({          textGenerationModelSelection: {            provider: ProviderDriverKind.make("codex"),            model: "gpt-5.4-mini",            options: { reasoningEffort: "low" },          },        });         assert.deepEqual(decoded.textGenerationModelSelection, {          instanceId: ProviderInstanceId.make("codex"),          model: "gpt-5.4-mini",          options: [{ id: "reasoningEffort", value: "low" }],        });      }),  );   it.effect("deep merges nested settings updates without dropping siblings", () =>    Effect.gen(function* () {      const serverSettings = yield* ServerSettingsModule.ServerSettingsService;       yield* serverSettings.updateSettings({        providers: {          codex: {            binaryPath: "/usr/local/bin/codex",            homePath: "/Users/julius/.codex",          },          claudeAgent: {            binaryPath: "/usr/local/bin/claude",            customModels: ["claude-custom"],          },        },        textGenerationModelSelection: {          instanceId: ProviderInstanceId.make("codex"),          model: DEFAULT_SERVER_SETTINGS.textGenerationModelSelection.model,          options: createModelSelection(            ProviderInstanceId.make("codex"),            DEFAULT_SERVER_SETTINGS.textGenerationModelSelection.model,            [              { id: "reasoningEffort", value: "high" },              { id: "fastMode", value: true },            ],          ).options!,        },      });       const next = yield* serverSettings.updateSettings({        providers: {          codex: {            binaryPath: "/opt/homebrew/bin/codex",          },        },        textGenerationModelSelection: {          options: [{ id: "fastMode", value: false }],        },      });       assert.deepEqual(next.providers.codex, {        enabled: true,        binaryPath: "/opt/homebrew/bin/codex",        homePath: "/Users/julius/.codex",        shadowHomePath: "",        launchArgs: "",        customModels: [],      });      assert.deepEqual(next.providers.claudeAgent, {        enabled: true,        binaryPath: "/usr/local/bin/claude",        homePath: "",        customModels: ["claude-custom"],        launchArgs: "",        autoCompactWindow: "",      });      assert.deepEqual(        next.textGenerationModelSelection,        createModelSelection(          ProviderInstanceId.make("codex"),          DEFAULT_SERVER_SETTINGS.textGenerationModelSelection.model,          [            { id: "reasoningEffort", value: "high" },            { id: "fastMode", value: false },          ],        ),      );    }).pipe(Effect.provide(makeServerSettingsLayer())),  );   it.effect("buffers changes after a subscription is acquired but before it is consumed", () =>    Effect.scoped(      Effect.gen(function* () {        const serverSettings = yield* ServerSettingsModule.ServerSettingsService;        const changes = yield* serverSettings.subscribeChanges;         yield* serverSettings.updateSettings({          providers: {            codex: {              binaryPath: "/usr/local/bin/codex-next",            },          },        });         const firstChange = yield* changes.pipe(Stream.runHead, Effect.timeout("1 second"));        assert.equal(          Option.getOrUndefined(firstChange)?.providers.codex.binaryPath,          "/usr/local/bin/codex-next",        );      }),    ).pipe(Effect.provide(makeServerSettingsLayer())),  );   it.effect("persists custom usage prices and removes them from the settings file", () =>    Effect.scoped(      Effect.gen(function* () {        const serverConfig = yield* ServerConfig.ServerConfig;        const fileSystem = yield* FileSystem.FileSystem;        const serverSettings = yield* ServerSettingsModule.ServerSettingsService;        const prices = {          inputCostPerMillionTokens: 2,          outputCostPerMillionTokens: 8,          cacheReadCostPerMillionTokens: 0,        };        const readPersisted = fileSystem          .readFileString(serverConfig.settingsPath)          .pipe(Effect.flatMap(Schema.decodeUnknownEffect(Schema.fromJsonString(ServerSettings))));         yield* serverSettings.updateSettings({ usagePriceOverrides: { "example-model": prices } });        const persisted = yield* readPersisted;        assert.deepStrictEqual(persisted.usagePriceOverrides, { "example-model": prices });         yield* serverSettings.updateSettings({ usagePriceOverrides: { "example-model": null } });        const restored = yield* readPersisted;        assert.deepStrictEqual(restored.usagePriceOverrides, {});      }),    ).pipe(Effect.provide(makeServerSettingsLayer())),  );   it.effect("persists and broadcasts thread settlement settings", () =>    Effect.scoped(      Effect.gen(function* () {        const serverConfig = yield* ServerConfig.ServerConfig;        const fileSystem = yield* FileSystem.FileSystem;        const serverSettings = yield* ServerSettingsModule.ServerSettingsService;        const changes = yield* serverSettings.subscribeChanges;         const next = yield* serverSettings.updateSettings({          sidebarAutoSettleAfterDays: null,          sidebarAutoSettleOnMerge: false,        });        const change = Option.getOrUndefined(yield* Stream.runHead(changes));        const raw = yield* fileSystem.readFileString(serverConfig.settingsPath);        // Inspect raw persisted JSON before schema decoding can apply defaults.        // @effect-diagnostics-next-line preferSchemaOverJson:off        const persisted = JSON.parse(raw) as Record<string, unknown>;         assert.strictEqual(next.sidebarAutoSettleAfterDays, null);        assert.isFalse(next.sidebarAutoSettleOnMerge);        assert.strictEqual(change?.sidebarAutoSettleAfterDays, null);        assert.isFalse(change?.sidebarAutoSettleOnMerge);        assert.strictEqual(persisted.sidebarAutoSettleAfterDays, null);        assert.isFalse(persisted.sidebarAutoSettleOnMerge);      }),    ).pipe(Effect.provide(makeServerSettingsLayer())),  );   it.effect("preserves model when switching providers via textGenerationModelSelection", () =>    Effect.gen(function* () {      const serverSettings = yield* ServerSettingsModule.ServerSettingsService;       // Start with Claude text generation selection      yield* serverSettings.updateSettings({        textGenerationModelSelection: {          instanceId: ProviderInstanceId.make("claudeAgent"),          model: "claude-sonnet-4-6",          options: createModelSelection(            ProviderInstanceId.make("claudeAgent"),            "claude-sonnet-4-6",            [{ id: "effort", value: "high" }],          ).options!,        },      });       // Switch to Codex — the stale Claude "effort" in options must not      // cause the update to lose the selected model.      const next = yield* serverSettings.updateSettings({        textGenerationModelSelection: {          instanceId: ProviderInstanceId.make("codex"),          model: "gpt-5.4",          options: createModelSelection(ProviderInstanceId.make("codex"), "gpt-5.4", [            { id: "reasoningEffort", value: "high" },          ]).options!,        },      });       assert.deepEqual(        next.textGenerationModelSelection,        createModelSelection(ProviderInstanceId.make("codex"), "gpt-5.4", [          { id: "reasoningEffort", value: "high" },        ]),      );    }).pipe(Effect.provide(makeServerSettingsLayer())),  );   it.effect("preserves custom provider instance text generation selections", () =>    Effect.gen(function* () {      const serverSettings = yield* ServerSettingsModule.ServerSettingsService;       const next = yield* serverSettings.updateSettings({        providerInstances: {          [ProviderInstanceId.make("claude_openrouter")]: {            driver: ProviderDriverKind.make("claudeAgent"),            enabled: true,            config: { customModels: ["openai/gpt-5.5"] },          },        },        textGenerationModelSelection: {          instanceId: ProviderInstanceId.make("claude_openrouter"),          model: "openai/gpt-5.5",        },      });       assert.deepEqual(next.textGenerationModelSelection, {        instanceId: ProviderInstanceId.make("claude_openrouter"),        model: "openai/gpt-5.5",      });    }).pipe(Effect.provide(makeServerSettingsLayer())),  );   it.effect(    "uses explicit provider instance enabled state over legacy provider enabled state",    () =>      Effect.gen(function* () {        const serverSettings = yield* ServerSettingsModule.ServerSettingsService;        const instanceId = ProviderInstanceId.make("claude_openrouter");         const next = yield* serverSettings.updateSettings({          providers: {            claudeAgent: {              enabled: false,            },          },          providerInstances: {            [instanceId]: {              driver: ProviderDriverKind.make("claudeAgent"),              enabled: true,              config: { customModels: ["openai/gpt-5.5"] },            },          },          textGenerationModelSelection: {            instanceId,            model: "openai/gpt-5.5",          },        });         assert.deepEqual(next.textGenerationModelSelection, {          instanceId,          model: "openai/gpt-5.5",        });      }).pipe(Effect.provide(makeServerSettingsLayer())),  );   it.effect("preserves enabled text generation selections for non-built-in drivers", () =>    Effect.gen(function* () {      const serverSettings = yield* ServerSettingsModule.ServerSettingsService;      const instanceId = ProviderInstanceId.make("openrouter_text");       const next = yield* serverSettings.updateSettings({        providerInstances: {          [instanceId]: {            driver: ProviderDriverKind.make("openrouter"),            enabled: true,            config: { customModels: ["openai/gpt-5.5"] },          },        },        textGenerationModelSelection: {          instanceId,          model: "openai/gpt-5.5",        },      });       assert.deepEqual(next.textGenerationModelSelection, {        instanceId,        model: "openai/gpt-5.5",      });    }).pipe(Effect.provide(makeServerSettingsLayer())),  );   it.effect(    "preserves the source control writer selection when its provider instance is disabled",    () =>      Effect.gen(function* () {        const serverSettings = yield* ServerSettingsModule.ServerSettingsService;        const serverConfig = yield* ServerConfig.ServerConfig;        const fileSystem = yield* FileSystem.FileSystem;        const instanceId = ProviderInstanceId.make("codex_writer");        const sourceControlWriterModelSelection = {          instanceId,          model: "gpt-5.4-mini",        };         yield* serverSettings.updateSettings({          providerInstances: {            [instanceId]: {              driver: ProviderDriverKind.make("codex"),              enabled: true,              config: {},            },          },          sourceControlWriterModelSelection,        });         const next = yield* serverSettings.updateSettings({          providerInstances: {            [instanceId]: {              driver: ProviderDriverKind.make("codex"),              enabled: false,              config: {},            },          },        });         assert.deepEqual(next.sourceControlWriterModelSelection, sourceControlWriterModelSelection);        assert.deepEqual(          ServerSettingsModule.resolveSourceControlWriterModelSelection(next),          next.textGenerationModelSelection,        );        assert.deepEqual(          (yield* serverSettings.getSettings).sourceControlWriterModelSelection,          sourceControlWriterModelSelection,        );         const raw = yield* fileSystem.readFileString(serverConfig.settingsPath);        assert.deepEqual(          // @effect-diagnostics-next-line preferSchemaOverJson:off          JSON.parse(raw).sourceControlWriterModelSelection,

Lines 1–500 of 1282.