import { type ChromeDensity } from "./chrome-density.js"; import { type SettingsError, type SettingsScope, type SettingsStorage } from "./settings-storage.js"; import type { BranchSummarySettings, CompactionSettings, PackageSource, Settings, ThinkingBudgetsSettings, TransportSetting, WarningSettings } from "./settings-types.js"; import { type ToolOutputView } from "./tool-output-view.js"; import type { WebtoolsSearchSettings } from "./tools/webtools-shared.js"; /** The `/learn` thresholds, which are flat top-level numeric settings. */ export type LearnSettingKey = "learnMaxSessions" | "learnMaxAgeDays" | "learnMinRepeats" | "learnMinRequestRepeats" | "learnMaxProposals"; export type { SettingsError, SettingsScope, SettingsStorage }; export type { BranchSummarySettings, CompactionSettings, ImageSettings, PackageSource, RetrySettings, Settings, ThinkingBudgetsSettings, TransportSetting, WarningSettings, } from "./settings-types.js"; 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, agentDir?: string): SettingsManager; /** Create a SettingsManager from an arbitrary storage backend */ static fromStorage(storage: SettingsStorage): SettingsManager; /** Create an in-memory SettingsManager (no file I/O) */ static inMemory(settings?: Partial): SettingsManager; private static loadFromStorage; private static tryLoadFromStorage; /** Migrate old settings format to new format */ private static migrateSettings; getGlobalSettings(): Settings; getProjectSettings(): Settings; getDefaultSettings(): Settings; reload(): 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 cloneModifiedNestedFields; private persistScopedSettings; private save; private saveProjectSettings; flush(): Promise; drainErrors(): SettingsError[]; getLastChangelogVersion(): string | undefined; setLastChangelogVersion(version: string): void; getSessionDir(): string | undefined; 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; getTransport(): TransportSetting; setTransport(transport: TransportSetting): void; getCompactionEnabled(): boolean; setCompactionEnabled(enabled: boolean): void; getCompactionReserveTokens(): number; getCompactionKeepRecentTokens(): number; getCompactionSettings(): Required; /** * Window and threshold `/learn` mines sessions with. * * Each value falls back to its default unless it is a finite positive number, * so a typo (`0`, `-1`, a pasted string) cannot silently reduce the window to * nothing and make the command report "no recent sessions". */ getLearnSettings(): { maxSessions: number; maxAgeDays: number; minRepeats: number; minRequestRepeats: number; maxProposals: number; }; /** Configured `fast`/`standard`/`capable` tiers, for callers resolving a category. */ getModelCategories(): Settings["modelCategories"]; /** * Persist one `/learn` threshold to the user scope. * * One keyed setter rather than five identical ones: the settings are flat * top-level numbers that differ only in name, and the settings pane drives * them from a table. Values are floored to at least 1, matching the read * side's refusal to let a zero shrink the window to nothing. */ setLearnSetting(key: LearnSettingKey, value: number): void; /** Byte cap on a single read/bash tool result before truncation. Clamped to >= 1024. */ getToolOutputMaxBytes(): number; setToolOutputMaxBytes(bytes: number): void; /** Line cap on a single read/bash tool result before truncation. Clamped to >= 1. */ getToolOutputMaxLines(): number; setToolOutputMaxLines(lines: number): void; /** Whether to stub superseded read results out of the outgoing context. */ getContextGcEnabled(): boolean; setContextGcEnabled(enabled: boolean): void; /** Trailing-silence window (ms) before voice capture auto-stops. Clamped to 300-10000. */ getVoiceSilenceMs(): number; setVoiceSilenceMs(ms: number): void; /** * Per-request timeout (seconds) for the webfetch/websearch binary. Settings * takes precedence, then the `HOOCODE_WEBTOOLS_TIMEOUT` env var, then the * default 15 (mirrors {@link getClearOnShrink}). Clamped to 1-120; a * non-finite settings value or malformed env falls through to the next tier. */ getWebtoolsTimeoutSecs(): number; /** * The `webtools.search` block as the binary would read it (backend choice and * credentials). hoocode only reads it, to tell whether `websearch` has a keyed * provider; the binary itself resolves the actual key at call time. * * Deliberately the user-level file rather than the merged view: the binary * reads only `~/.hoocode/settings.json`, so a key in a project's * `.hoocode/settings.json` never reaches it, and treating one as configured * would silence the warning for a search that still runs keyless. (Contrast * {@link getWebtoolsTimeoutSecs}, which is hoocode's own setting forwarded as * a flag, so there the merged value is the effective one.) */ getWebtoolsSearch(): WebtoolsSearchSettings | undefined; setWebtoolsTimeoutSecs(secs: number): void; /** Tool names disabled from the TUI; removed from the agent in every session. */ getDisabledTools(): string[]; setDisabledTools(names: string[]): void; /** * How much of a tool call the transcript shows (radar / peek / full). * * Settings files written before the dial existed carry the old three-value * `toolOutputDisplay` key. They are read here rather than rewritten on load, * so a downgrade keeps working until the user actually changes the setting. */ getToolOutputView(): ToolOutputView; setToolOutputView(view: ToolOutputView): void; /** * The chrome dial's stop, or undefined when the user has never set one. * * Deliberately not defaulted here. "Unset" is a real state: it is what lets * a short terminal open at `compact` without that guess ever overruling a * choice someone actually made. The caller resolves it (see * `SMALL_TERMINAL_ROWS`), because only the caller knows the terminal size. */ getChromeDensity(): ChromeDensity | undefined; setChromeDensity(density: ChromeDensity): void; /** Persisted overrides for extension-registered flags (name -> value). */ getFlagOverrides(): Record; setFlagOverride(name: string, value: boolean | string): void; clearFlagOverride(name: string): void; getBranchSummarySettings(): Required; getBranchSummarySkipPrompt(): boolean; getRetryEnabled(): boolean; setRetryEnabled(enabled: boolean): void; getRetrySettings(): { enabled: boolean; maxRetries: number; baseDelayMs: number; }; getProviderRetrySettings(): { timeoutMs?: number; maxRetries?: number; maxRetryDelayMs: 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; getNpmCommand(): string[] | undefined; setNpmCommand(command: string[] | undefined): void; getCollapseChangelog(): boolean; setCollapseChangelog(collapse: boolean): void; getEnableInstallTelemetry(): boolean; setEnableInstallTelemetry(enabled: 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; getSlashCommandPaths(): string[]; setSlashCommandPaths(paths: string[]): void; setProjectSlashCommandPaths(paths: string[]): void; getThemePaths(): string[]; setThemePaths(paths: string[]): void; setProjectThemePaths(paths: string[]): void; getEnableSkillCommands(): boolean; setEnableSkillCommands(enabled: boolean): void; getEnableSubagent(): boolean; setEnableSubagent(enabled: boolean): void; /** Whether to dispatch eligible subagents on reused warm workers (experimental). */ getWarmSubagents(): boolean; setWarmSubagents(enabled: boolean): void; /** Tree-wide subagent nesting cap. Clamped to >= 1 (delegation can never be disabled here). */ getMaxSubagentDepth(): number; /** Max concurrent subagents per pool at nesting depth >= 1. Clamped to >= 1. */ getNestedSubagentConcurrency(): number; getEnableTodoWrite(): boolean; setEnableTodoWrite(enabled: boolean): void; /** Raw `platform` tokens (string coerced to an array), or undefined when unset. */ getPlatform(): string[] | undefined; /** * Persist the artifact platform targets. Always stored as an array (getPlatform * accepts either shape), and an empty/undefined list removes the key so the * per-consumer defaults apply again rather than an empty list being read as * "target nothing". Global scope: the layout a machine writes is an * environment-level choice, not a per-repo one. */ setPlatform(platforms: readonly string[] | undefined): void; getEnablePluginTools(): boolean; setEnablePluginTools(enabled: boolean): void; /** * Where an autonomous InstallPlugin puts a plugin. `/plugin install` asks the * human instead of reading this — the setting exists precisely for the path * where there is nobody to ask. */ getPluginInstallScope(): "user" | "project"; setPluginInstallScope(scope: "user" | "project"): void; getDeferMcpSchemas(): boolean; setDeferMcpSchemas(enabled: boolean): void; getEnableWebTools(): boolean; setEnableWebTools(enabled: boolean): void; getEnableSemanticIndex(): boolean; setEnableSemanticIndex(enabled: boolean): void; getEmbsearchBinaryPath(): string | undefined; getEmbsearchThresholdBytes(): number; getLight(): boolean; setLight(enabled: boolean): void; getThinkingBudgets(): ThinkingBudgetsSettings | undefined; getThinkingDisplay(): "summarized" | "omitted" | undefined; getShowImages(): boolean; setShowImages(show: boolean): void; getImageWidthCells(): number; setImageWidthCells(width: number): void; getClearOnShrink(): boolean; setClearOnShrink(enabled: boolean): void; getShowTerminalProgress(): boolean; setShowTerminalProgress(enabled: boolean): void; getChimeOnTurnComplete(): boolean; setChimeOnTurnComplete(enabled: boolean): void; getTipsEnabled(): boolean; setTipsEnabled(enabled: boolean): void; getSeenTips(): string[]; /** * Remember that a tip has been shown. * * Idempotent, so a tip repeated in a long session does not grow the list. The * list is bounded by the number of tips that exist, and an id that is no * longer in `TIPS` is harmless -- it is only ever tested for membership. */ markTipSeen(id: string): void; getStarNudgeCount(): number; recordStarNudge(): 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; getTreeFilterMode(): "default" | "no-tools" | "user-only" | "labeled-only" | "all"; setTreeFilterMode(mode: "default" | "no-tools" | "user-only" | "labeled-only" | "all"): void; getShowHardwareCursor(): boolean; setShowHardwareCursor(enabled: boolean): void; getEditorBorder(): "rule" | "box"; setEditorBorder(border: "rule" | "box"): void; getEditorPaddingX(): number; setEditorPaddingX(padding: number): void; getAutocompleteMaxVisible(): number; setAutocompleteMaxVisible(maxVisible: number): void; getCodeBlockIndent(): string; getWarnings(): WarningSettings; setWarnings(warnings: WarningSettings): void; } //# sourceMappingURL=settings-manager.d.ts.map