| 1 | # settings.py DOX |
| 2 | |
| 3 | ## Purpose |
| 4 | |
| 5 | - Own the `settings.py` helper module. |
| 6 | - This module defines settings models, defaults, validation, and serialization. |
| 7 | - Keep this file-level DOX profile synchronized with `settings.py` because this directory is intentionally flat. |
| 8 | |
| 9 | ## Ownership |
| 10 | |
| 11 | - `settings.py` owns the runtime implementation. |
| 12 | - `settings.py.dox.md` owns durable notes about responsibilities, contracts, side effects, and verification for that implementation. |
| 13 | - Classes: |
| 14 | - `Settings` (`TypedDict`) |
| 15 | - `PartialSettings` (`Settings`) |
| 16 | - `FieldOption` (`TypedDict`) |
| 17 | - `SettingsField` (`TypedDict`) |
| 18 | - `SettingsSection` (`TypedDict`) |
| 19 | - `ModelProvider` (`ProvidersFO`) |
| 20 | - `SettingsOutputAdditional` (`TypedDict`) |
| 21 | - `SettingsOutput` (`TypedDict`) |
| 22 | - Top-level functions: |
| 23 | - `get_default_value(name: str, value: T) -> T`: Load setting value from .env with A0_SET_ prefix, falling back to default. |
| 24 | - `_ensure_option_present(options: list[OptionT] | None, current_value: str | None) -> list[OptionT]`: Ensure the currently selected value exists in a dropdown options list. |
| 25 | - `_is_valid_timezone(value: str) -> bool` |
| 26 | - `_normalize_timezone_setting(value: Any, default: str=...) -> str` |
| 27 | - `_normalize_time_format(value: Any, default: str=...) -> str` |
| 28 | - `_normalize_ui_control_visibility(value: Any) -> dict[str, dict[str, bool]]` |
| 29 | - `_resolve_runtime_timezone(setting_value: str, browser_timezone: str | None=...) -> str` |
| 30 | - `_timezone_options() -> list[FieldOption]` |
| 31 | - `convert_out(settings: Settings) -> SettingsOutput` |
| 32 | - `_get_api_key_field(settings: Settings, provider: str, title: str) -> SettingsField` |
| 33 | - `convert_in(settings: Settings) -> Settings` |
| 34 | - `get_settings() -> Settings` |
| 35 | - `reload_settings() -> Settings` |
| 36 | - `set_runtime_settings_snapshot(settings: Settings) -> None` |
| 37 | - `set_settings(settings: Settings, apply: bool=..., browser_timezone: str | None=...)` |
| 38 | - `set_settings_delta(delta: dict, apply: bool=...)` |
| 39 | - `merge_settings(original: Settings, delta: dict) -> Settings` |
| 40 | - `normalize_settings(settings: Settings) -> Settings` |
| 41 | - `_adjust_to_version(settings: Settings, default: Settings)` |
| 42 | - `_load_sensitive_settings(settings: Settings)` |
| 43 | - `_read_settings_file() -> Settings | None` |
| 44 | - `_write_settings_file(settings: Settings)` |
| 45 | - `_remove_sensitive_settings(settings: Settings)` |
| 46 | - `_write_sensitive_settings(settings: Settings)` |
| 47 | - `get_default_settings() -> Settings` |
| 48 | - `_apply_timezone_setting(previous: Settings | None, browser_timezone: str | None=...) -> None` |
| 49 | - `_apply_settings(previous: Settings | None, browser_timezone: str | None=...)` |
| 50 | - `_env_to_dict(data: str)` |
| 51 | - `_dict_to_env(data_dict)` |
| 52 | - `set_root_password(password: str)` |
| 53 | - `get_runtime_config(set: Settings)` |
| 54 | - Notable constants/configuration names: `T`, `PASSWORD_PLACEHOLDER`, `API_KEY_PLACEHOLDER`, `TIMEZONE_AUTO`, `TIME_FORMAT_12H`, `TIME_FORMAT_24H`, `UI_CONTROL_VISIBILITY_DEFAULTS`, `SETTINGS_FILE`. |
| 55 | |
| 56 | ## Runtime Contracts |
| 57 | |
| 58 | - Helper modules own reusable framework APIs and must preserve public callers unless all callers, tests, and docs are updated together. |
| 59 | - Update this file whenever public functions, classes, persistence behavior, path/security assumptions, side effects, or cross-module contracts change. |
| 60 | - Observed side-effect areas: filesystem reads, filesystem writes, filesystem deletion, network calls, subprocess/runtime control, model calls, WebSocket state, plugin state, settings/state persistence, secret handling, scheduler state. |
| 61 | - Imported dependency areas include: `base64`, `hashlib`, `helpers`, `helpers.notification`, `helpers.print_style`, `helpers.providers`, `helpers.secrets`, `json`, `models`, `os`, `pytz`, `re`, `subprocess`, `typing`. |
| 62 | |
| 63 | ## Key Concepts |
| 64 | |
| 65 | - Important called helpers/classes observed in the source: `TypeVar`, `files.get_abs_path`, `dotenv.get_dotenv_value`, `opts.insert`, `str.strip`, `_is_valid_timezone`, `str.strip.lower`, `_normalize_timezone_setting`, `SettingsOutput`, `get_default_settings`, `_ensure_option_present`, `_resolve_runtime_timezone`, `get_default_secrets_manager`, `get_settings`, `get_settings_for_prompt`, `normalize_settings`, `_load_sensitive_settings`, `deepcopy`, `settings.copy`, `_write_settings_file`, `reload_settings`, `set_settings`, `initialize_agent`. |
| 66 | - Applying settings refreshes active context configs while preserving each subordinate agent's own profile. |
| 67 | - Applying settings starts a deferred `MCPConfig.update(...)` with the current `mcp_servers` string when global MCP server settings change. |
| 68 | - `get_settings()` retains normalize-on-read behavior. Prompt-building callers |
| 69 | explicitly use `get_settings_for_prompt()` to reuse one task-local snapshot |
| 70 | within each `Agent.prepare_prompt()` call. |
| 71 | - Explicit reloads also refresh an active prompt snapshot. |
| 72 | - `max_consecutive_unusable_responses` defaults to `5` and controls the cost circuit breaker for malformed or repeated main-model outputs. |
| 73 | - `ui_control_visibility` stores validated mobile and desktop visibility flags for the project selector, clock, connection status, context-window usage indicator, and right canvas rail; missing or malformed values fall back per device. |
| 74 | - The Global default-profile selector lists only globally available profiles. |
| 75 | A currently configured unavailable profile remains visible with an explicit |
| 76 | unavailable label so settings can round-trip it truthfully, except that the |
| 77 | exact `default` utility profile is never offered as a selectable option. |
| 78 | - Legacy settings that still name the hidden `default` utility profile normalize |
| 79 | to `agent0`, so newly created chats always start with a selectable profile. |
| 80 | - Keep request/response, tool, or helper semantics documented here at the same time as source changes. |
| 81 | |
| 82 | ## Work Guidance |
| 83 | |
| 84 | - Preserve public helper APIs used by core code and plugins unless every caller is updated. |
| 85 | - Keep path, auth, secret, persistence, network, and subprocess behavior explicit and bounded. |
| 86 | - Prefer adding cohesive helper functions here only when behavior is reused across modules. |
| 87 | |
| 88 | ## Verification |
| 89 | |
| 90 | - Run targeted tests for changed helper behavior; run security regressions for auth, filesystem, WebSocket, tunnel, upload, or secret-handling helpers. |
| 91 | - Related tests observed by source search: |
| 92 | - `tests/test_browser_agent_regressions.py` |
| 93 | - `tests/test_document_query_plugin.py` |
| 94 | - `tests/test_download_toast_regressions.py` |
| 95 | - `tests/test_fasta2a_client.py` |
| 96 | - `tests/test_mcp_handler_multimodal.py` |
| 97 | - `tests/test_model_config_api_keys.py` |
| 98 | - `tests/test_model_config_project_presets.py` |
| 99 | - `tests/test_oauth_static.py` |
| 100 | - `tests/test_subagent_profiles.py` |
| 101 | |
| 102 | ## Child DOX Index |
| 103 | |
| 104 | No child DOX files. |