| @@ -3,41 +3,43 @@ import { Option, Schema } from "effect"; · 2 unmodified lines |
| 3 | import { TrimmedNonEmptyString, type ProviderKind } from "@t3tools/contracts"; | 3 | import { TrimmedNonEmptyString, type ProviderKind } from "@t3tools/contracts"; |
| 4 | import { getDefaultModel, getModelOptions, normalizeModelSlug } from "@t3tools/shared/model"; | 4 | import { getDefaultModel, getModelOptions, normalizeModelSlug } from "@t3tools/shared/model"; |
| 5 | import { useLocalStorage } from "./hooks/useLocalStorage"; | 5 | import { useLocalStorage } from "./hooks/useLocalStorage"; |
| | 6 | import { EnvMode } from "./components/BranchToolbar.logic"; |
| 6 | | 7 | |
| 7 | const APP_SETTINGS_STORAGE_KEY = "t3code:app-settings:v1"; | 8 | const APP_SETTINGS_STORAGE_KEY = "t3code:app-settings:v1"; |
| 8 | const MAX_CUSTOM_MODEL_COUNT = 32; | 9 | const MAX_CUSTOM_MODEL_COUNT = 32; |
| 9 | export const MAX_CUSTOM_MODEL_LENGTH = 256; | 10 | export const MAX_CUSTOM_MODEL_LENGTH = 256; |
| 10 | export const TIMESTAMP_FORMAT_OPTIONS = ["locale", "12-hour", "24-hour"] as const; | 11 | |
| 11 | export type TimestampFormat = (typeof TIMESTAMP_FORMAT_OPTIONS)[number]; | 12 | export const TimestampFormat = Schema.Literals(["locale", "12-hour", "24-hour"]); |
| | 13 | export type TimestampFormat = typeof TimestampFormat.Type; |
| 12 | export const DEFAULT_TIMESTAMP_FORMAT: TimestampFormat = "locale"; | 14 | export const DEFAULT_TIMESTAMP_FORMAT: TimestampFormat = "locale"; |
| | 15 | |
| 13 | const BUILT_IN_MODEL_SLUGS_BY_PROVIDER: Record<ProviderKind, ReadonlySet<string>> = { | 16 | const BUILT_IN_MODEL_SLUGS_BY_PROVIDER: Record<ProviderKind, ReadonlySet<string>> = { |
| 14 | codex: new Set(getModelOptions("codex").map((option) => option.slug)), | 17 | codex: new Set(getModelOptions("codex").map((option) => option.slug)), |
| 15 | claudeAgent: new Set(getModelOptions("claudeAgent").map((option) => option.slug)), | 18 | claudeAgent: new Set(getModelOptions("claudeAgent").map((option) => option.slug)), |
| 16 | }; | 19 | }; |
| 17 | | 20 | |
| 18 | const AppSettingsSchema = Schema.Struct({ | 21 | const withDefaults = |
| 19 | codexBinaryPath: Schema.String.check(Schema.isMaxLength(4096)).pipe( | 22 | < |
| 20 | Schema.withConstructorDefault(() => Option.some("")), | 23 | S extends Schema.Top & Schema.WithoutConstructorDefault, |
| 21 | ), | 24 | D extends S["~type.make.in"] & S["Encoded"], |
| 22 | codexHomePath: Schema.String.check(Schema.isMaxLength(4096)).pipe( | 25 | >( |
| 23 | Schema.withConstructorDefault(() => Option.some("")), | 26 | fallback: () => D, |
| 24 | ), | 27 | ) => |
| 25 | defaultThreadEnvMode: Schema.Literals(["local", "worktree"]).pipe( | 28 | (schema: S) => |
| 26 | Schema.withConstructorDefault(() => Option.some("local")), | 29 | schema.pipe( |
| 27 | ), | 30 | Schema.withConstructorDefault(() => Option.some(fallback())), |
| 28 | confirmThreadDelete: Schema.Boolean.pipe(Schema.withConstructorDefault(() => Option.some(true))), | 31 | Schema.withDecodingDefault(() => fallback()), |
| 29 | enableAssistantStreaming: Schema.Boolean.pipe( | 32 | ); |
| 30 | Schema.withConstructorDefault(() => Option.some(false)), | 33 | |
| 31 | ), | 34 | export const AppSettingsSchema = Schema.Struct({ |
| 32 | timestampFormat: Schema.Literals(["locale", "12-hour", "24-hour"]).pipe( | 35 | codexBinaryPath: Schema.String.check(Schema.isMaxLength(4096)).pipe(withDefaults(() => "")), |
| 33 | Schema.withConstructorDefault(() => Option.some(DEFAULT_TIMESTAMP_FORMAT)), | 36 | codexHomePath: Schema.String.check(Schema.isMaxLength(4096)).pipe(withDefaults(() => "")), |
| 34 | ), | 37 | defaultThreadEnvMode: EnvMode.pipe(withDefaults(() => "local" as const satisfies EnvMode)), |
| 35 | customCodexModels: Schema.Array(Schema.String).pipe( | 38 | confirmThreadDelete: Schema.Boolean.pipe(withDefaults(() => true)), |
| 36 | Schema.withConstructorDefault(() => Option.some([])), | 39 | enableAssistantStreaming: Schema.Boolean.pipe(withDefaults(() => false)), |
| 37 | ), | 40 | timestampFormat: TimestampFormat.pipe(withDefaults(() => DEFAULT_TIMESTAMP_FORMAT)), |
| 38 | customClaudeModels: Schema.Array(Schema.String).pipe( | 41 | customCodexModels: Schema.Array(Schema.String).pipe(withDefaults(() => [])), |
| 39 | Schema.withConstructorDefault(() => Option.some([])), | 42 | customClaudeModels: Schema.Array(Schema.String).pipe(withDefaults(() => [])), |
| 40 | ), | | |
| 41 | textGenerationModel: Schema.optional(TrimmedNonEmptyString), | 43 | textGenerationModel: Schema.optional(TrimmedNonEmptyString), |
| 42 | }); | 44 | }); |
| 43 | export type AppSettings = typeof AppSettingsSchema.Type; | 45 | export type AppSettings = typeof AppSettingsSchema.Type; |