/** * [WHO]: SettingsManager class, two-tier settings (global + project-local), agent loop defaults * [FROM]: Depends on ai, node:fs, proper-lockfile, config.ts * [TO]: Consumed by index.ts, main.ts, core/runtime/sdk.ts, cli/config-selector.ts, extensions/builtin/team/index.ts, modes/interactive/components/model-selector.ts, modes/interactive/components/config-selector.ts, and test files * [HERE]: core/platform/config/settings-manager.ts - user preferences aggregation */ import type { Transport } from "@catui/ai/types"; import { type AgentDirContext } from "../../agent-dir/agent-dir-context.js"; export interface CompactionSettings { enabled?: boolean; reserveTokens?: number; keepRecentTokens?: number; } export interface BranchSummarySettings { reserveTokens?: number; } export interface RetrySettings { enabled?: boolean; maxRetries?: number; baseDelayMs?: number; maxDelayMs?: number; } export interface AgentLoopSettings { maxToolResultBatchSizeChars?: number; } export interface TerminalSettings { showImages?: boolean; clearOnShrink?: boolean; showTokenStats?: boolean; showWorkingTrace?: boolean; showMemoryTrace?: boolean; buddyEnabled?: boolean; buddySpecies?: number; } export interface ImageSettings { autoResize?: boolean; blockImages?: boolean; } export interface ThinkingBudgetsSettings { minimal?: number; low?: number; medium?: number; high?: number; } export interface MarkdownSettings { codeBlockIndent?: string; } export type TransportSetting = Transport; export type AgentLoopFrameworkSetting = "standard" | "weak-model-compatible"; export type AgentLoopFrameworkSettingInput = AgentLoopFrameworkSetting | "high-intelligence" | "low-intelligence" | "structured-adaptive"; export declare function normalizeAgentLoopFrameworkSetting(value: AgentLoopFrameworkSettingInput | undefined): AgentLoopFrameworkSetting | undefined; /** * Package source for npm/git packages. * - String form: load all resources from the package * - Object form: filter which resources to load */ export type PackageSource = string | { source: string; extensions?: string[]; skills?: string[]; prompts?: string[]; themes?: string[]; }; export interface Settings { locale?: "en" | "zh"; lastChangelogVersion?: string; defaultProvider?: string; defaultModel?: string; defaultThinkingLevel?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh"; agentLoopFramework?: AgentLoopFrameworkSettingInput; agentLoop?: AgentLoopSettings; transport?: TransportSetting; steeringMode?: "all" | "one-at-a-time"; followUpMode?: "all" | "one-at-a-time"; theme?: string; compaction?: CompactionSettings; branchSummary?: BranchSummarySettings; retry?: RetrySettings; hideThinkingBlock?: boolean; shellPath?: string; quietStartup?: boolean; shellCommandPrefix?: string; collapseChangelog?: boolean; packages?: PackageSource[]; extensions?: string[]; skills?: string[]; prompts?: string[]; themes?: string[]; enableSkillCommands?: boolean; terminal?: TerminalSettings; images?: ImageSettings; enabledModels?: string[]; doubleEscapeAction?: "fork" | "tree" | "none"; thinkingBudgets?: ThinkingBudgetsSettings; editorPaddingX?: number; autocompleteMaxVisible?: number; showHardwareCursor?: boolean; markdown?: MarkdownSettings; /** Directory for plan mode files. Relative paths must stay inside the project root. */ plansDirectory?: string; /** NanoMem / Dream settings */ nanomem?: { autoDream?: { enabled?: boolean; minHours?: number; minSessions?: number; scanIntervalMinutes?: number; }; dream?: { lockStaleMinutes?: number; }; }; /** Presence extension settings - AI greeting and idle messages */ presence?: { enabled?: boolean; }; /** Next-step extension settings - Codex-style "suggest next steps" rule injected via before_agent_start */ nextStep?: { enabled?: boolean; }; /** IdleThink extension settings - background code exploration during idle */ idleThink?: { enabled?: boolean; idleMinutes?: number; dailyBudget?: number; maxDurationMinutes?: number; }; /** Auto-update setting: 'always' = auto-update on startup, 'prompt' = ask user (default), 'never' = never check */ autoUpdate?: "always" | "prompt" | "never"; /** Last skipped version for update prompts */ skippedVersion?: string; } export type SettingsScope = "global" | "project"; export interface SettingsStorage { withLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void; withLockAsync(scope: SettingsScope, fn: (current: string | undefined) => Promise): Promise; readStorageAsync(scope: SettingsScope): Promise; } export interface SettingsError { scope: SettingsScope; error: Error; } export declare class FileSettingsStorage implements SettingsStorage { private globalSettingsPath; private projectSettingsPath; constructor(cwd?: string, ctx?: AgentDirContext); withLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void; withLockAsync(scope: SettingsScope, fn: (current: string | undefined) => Promise): Promise; readStorageAsync(scope: SettingsScope): Promise; } export declare class InMemorySettingsStorage implements SettingsStorage { private global; private project; withLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void; withLockAsync(scope: SettingsScope, fn: (current: string | undefined) => Promise): Promise; readStorageAsync(scope: SettingsScope): Promise; } export declare class SettingsManager { private storage; private globalSettings; private projectSettings; private settings; private modifiedFields; private modifiedNestedFields; private modifiedProjectFields; private modifiedProjectNestedFields; private globalSettingsLoadError; private projectSettingsLoadError; private writeQueue; private errors; private constructor(); /** Create a SettingsManager that loads from files */ static create(cwd?: string, ctxOrPath?: string | AgentDirContext): SettingsManager; /** Create a SettingsManager that loads from files async */ static createAsync(cwd?: string, ctxOrPath?: string | AgentDirContext): Promise; /** Create a SettingsManager from an arbitrary storage backend */ static fromStorage(storage: SettingsStorage): SettingsManager; /** Create a SettingsManager from an arbitrary storage backend async */ static fromStorageAsync(storage: SettingsStorage): Promise; /** Create an in-memory SettingsManager (no file I/O) */ static inMemory(settings?: Partial): SettingsManager; private static loadFromStorage; private static loadFromStorageAsync; private static tryLoadFromStorage; private static tryLoadFromStorageAsync; /** Migrate old settings format to new format */ private static migrateSettings; getGlobalSettings(): Settings; getProjectSettings(): Settings; /** Get merged effective settings (project overrides global). */ getSettings(): Settings; reload(): void; reloadAsync(): Promise; /** Apply additional overrides on top of current settings */ applyOverrides(overrides: Partial): void; /** Mark a global field as modified during this session */ private markModified; /** Mark a project field as modified during this session */ private markProjectModified; private recordError; private clearModifiedScope; private enqueueWrite; private enqueueWriteAsync; private cloneModifiedNestedFields; private persistScopedSettings; private persistScopedSettingsAsync; private save; private saveAsync; private saveProjectSettings; private saveProjectSettingsAsync; flush(): Promise; drainErrors(): SettingsError[]; getLastChangelogVersion(): string | undefined; setLastChangelogVersion(version: string): void; getDefaultProvider(): string | undefined; getDefaultModel(): string | undefined; setDefaultProvider(provider: string): void; setDefaultModel(modelId: string): void; setDefaultModelAndProvider(provider: string, modelId: string): void; getSteeringMode(): "all" | "one-at-a-time"; setSteeringMode(mode: "all" | "one-at-a-time"): void; getFollowUpMode(): "all" | "one-at-a-time"; setFollowUpMode(mode: "all" | "one-at-a-time"): void; getTheme(): string | undefined; setTheme(theme: string): void; getDefaultThinkingLevel(): "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | undefined; setDefaultThinkingLevel(level: "off" | "minimal" | "low" | "medium" | "high" | "xhigh"): void; getAgentLoopFramework(): AgentLoopFrameworkSetting | undefined; getAgentLoopSettings(): { maxToolResultBatchSizeChars: number; }; setAgentLoopFramework(framework: AgentLoopFrameworkSettingInput | undefined): void; getTransport(): TransportSetting; setTransport(transport: TransportSetting): void; getCompactionEnabled(): boolean; setCompactionEnabled(enabled: boolean): void; getCompactionReserveTokens(): number; getCompactionKeepRecentTokens(): number; getCompactionSettings(): { enabled: boolean; reserveTokens: number; keepRecentTokens: number; }; getBranchSummarySettings(): { reserveTokens: number; }; getRetryEnabled(): boolean; setRetryEnabled(enabled: boolean): void; getRetrySettings(): { enabled: boolean; maxRetries: number; baseDelayMs: number; maxDelayMs: number; }; getHideThinkingBlock(): boolean; setHideThinkingBlock(hide: boolean): void; getShellPath(): string | undefined; setShellPath(path: string | undefined): void; getQuietStartup(): boolean; setQuietStartup(quiet: boolean): void; getShellCommandPrefix(): string | undefined; setShellCommandPrefix(prefix: string | undefined): void; getCollapseChangelog(): boolean; setCollapseChangelog(collapse: boolean): void; getPackages(): PackageSource[]; setPackages(packages: PackageSource[]): void; setProjectPackages(packages: PackageSource[]): void; getExtensionPaths(): string[]; setExtensionPaths(paths: string[]): void; setProjectExtensionPaths(paths: string[]): void; getSkillPaths(): string[]; setSkillPaths(paths: string[]): void; setProjectSkillPaths(paths: string[]): void; getPromptTemplatePaths(): string[]; setPromptTemplatePaths(paths: string[]): void; setProjectPromptTemplatePaths(paths: string[]): void; getThemePaths(): string[]; setThemePaths(paths: string[]): void; setProjectThemePaths(paths: string[]): void; getEnableSkillCommands(): boolean; setEnableSkillCommands(enabled: boolean): void; getThinkingBudgets(): ThinkingBudgetsSettings | undefined; getShowImages(): boolean; setShowImages(show: boolean): void; getBuddyEnabled(): boolean; setBuddyEnabled(enabled: boolean): void; getBuddySpecies(): number; setBuddySpecies(species: number): void; getClearOnShrink(): boolean; setClearOnShrink(enabled: boolean): void; getShowTokenStats(): boolean; setShowTokenStats(enabled: boolean): void; getShowWorkingTrace(): boolean; setShowWorkingTrace(enabled: boolean): void; getShowMemoryTrace(): boolean; setShowMemoryTrace(enabled: boolean): void; getPresenceEnabled(): boolean; setPresenceEnabled(enabled: boolean): void; getNextStepEnabled(): boolean; setNextStepEnabled(enabled: boolean): void; getImageAutoResize(): boolean; setImageAutoResize(enabled: boolean): void; getBlockImages(): boolean; setBlockImages(blocked: boolean): void; getEnabledModels(): string[] | undefined; setEnabledModels(patterns: string[] | undefined): void; getDoubleEscapeAction(): "fork" | "tree" | "none"; setDoubleEscapeAction(action: "fork" | "tree" | "none"): void; getShowHardwareCursor(): boolean; setShowHardwareCursor(enabled: boolean): void; getEditorPaddingX(): number; setEditorPaddingX(padding: number): void; getAutocompleteMaxVisible(): number; setAutocompleteMaxVisible(maxVisible: number): void; getCodeBlockIndent(): string; getAutoUpdate(): "always" | "prompt" | "never"; setAutoUpdate(mode: "always" | "prompt" | "never"): void; getSkippedVersion(): string | undefined; setSkippedVersion(version: string | undefined): void; }