You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/ha_mcp/settings_ui/AGENTS.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -46,7 +46,7 @@ Any reachable HA instance works for `HOMEASSISTANT_URL` / `HOMEASSISTANT_TOKEN`.
46
46
-**Relative imports are double-dot.** This is a subpackage of `ha_mcp`, so siblings are `from ..config import ...`, `from ..tools.X import ...`, etc. A single dot resolves inside `settings_ui/` and will `ModuleNotFoundError`.
47
47
-**Python ↔ JS sentinel sync.**`__init__.py` substitutes `__HA_MCP_DEFAULT_PINNED__` and `__HA_MCP_MANDATORY__` into `settings.js` at load. The presence of both sentinels is asserted at import — a rename in one place that isn't mirrored in the other fails fast (not silently).
48
48
-**Anti-FOUC parity with the docs site (JS logic only, NOT visual design).** The theme/accessibility resolver core in `settings.js` (PREFS / PRESETS / apply functions / custom-color layering) must stay logically identical to `site/src/layouts/Layout.astro`. Enforced by `tests/src/unit/test_anti_fouc_parity.py`. Mirror any change in both, or that test fails. This is about *how a saved theme preference is applied before paint*, not about what the page looks like — the visual target is HA (see "Design goal").
49
-
-**Theme prefs persist server-side** (`theme_prefs.json`) because the stdio sidecar respawns on a random port (a fresh origin with empty `localStorage`). The page seeds only *missing*`localStorage` keys from the server payload; the browser's own latest choice wins.
49
+
-**Theme prefs persist server-side** (`theme_prefs.json`) because the stdio sidecar's port — the browser origin — can change (stable by default since #2131, but fresh on first spawn, a lost `ui.state`, a pin change, or a taken remembered port), and a new origin starts with empty `localStorage`. The page seeds only *missing*`localStorage` keys from the server payload; the browser's own latest choice wins.
50
50
-**Locale selection order is explicit cookie → Home Assistant `ha_lang` hint → `Accept-Language` → English.** Keep the selector cookie name synchronized with `_i18n.py`, and preserve English fallback for incomplete community translations.
51
51
-**Callouts use the `ha-alert` style.** Notice bars (`.ha-alert`, `.readonly-notice`, `.pin-notice`, `.restart-notice`) replicate HA's `ha-alert`: full type-tint background, rounded, leading mdi icon (`--icon-info` / `--icon-warning` masks), icon in an absolute left gutter so text flows full-width. Use this for new callouts, not a left-border bar.
Copy file name to clipboardExpand all lines: src/ha_mcp/settings_ui/locales/en.json
+2-2Lines changed: 2 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -63,7 +63,7 @@
63
63
"policies.pending.empty": "No pending approvals.",
64
64
"policies.rules.title": "Gated tools",
65
65
"policies.rules.empty": "No tools currently security-gated. Enable per-tool gating from the <a href=\"#\" data-panel-link=\"tools\">Tools</a> tab.",
66
-
"accessibility.intro": "These settings apply immediately and are saved in this browser and on the server, so they survive restarts in every mode (including stdio, where the settings page moves to a fresh port each session). The docs site offers the same controls in its navigation bar; it has no server and saves per browser.",
66
+
"accessibility.intro": "These settings apply immediately and are saved in this browser and on the server, so they survive restarts in every mode (including stdio, where the settings page can occasionally move to a new port). The docs site offers the same controls in its navigation bar; it has no server and saves per browser.",
67
67
"accessibility.storage_blocked": "Your browser is blocking site storage; choices apply for this session only.",
68
68
"accessibility.theme.title": "Theme",
69
69
"accessibility.theme.help": "One-click color schemes. Auto, the default, follows your OS preference and flips live when it changes.",
"advanced.extra_yaml_write_keys.help": "Comma-separated top-level keys ha_config_set_yaml may write in addition to the built-in ones, for YAML-first integrations on this install (e.g. alert2). Keys that redefine Home Assistant's own trust boundary can never be added and are ignored. Requires custom component 1.2.4 or newer.",
"advanced.sidecar_pin_port.help": "0 chooses a free port each restart; 1024–65535 pins a preferred port. Restart required.",
423
+
"advanced.sidecar_pin_port.help": "0 picks a free port on first start and keeps it for later restarts; 1024–65535 pins a preferred port (falls back to a free one if taken). Restart required.",
"advanced.enable_dev_mode.help": "⚠ Registers hidden tools that can change settings and replace the running server. Development and testing only. Restart required.",
code_mode_max_invocations: {label: "Code-mode max invocations",help: "API/tool-call cap per sandbox run. Restart required."},
3535
3535
code_mode_saved_tools_path:{label: "Saved-tools path",help: "JSON file where ha_manage_custom_tool persists saved tools across restarts. Restart required."},
3536
3536
extra_yaml_write_keys: {label: "Extra YAML write keys",help: "Comma-separated top-level keys ha_config_set_yaml may write in addition to the built-in ones, for YAML-first integrations on this install (e.g. alert2). Keys that redefine Home Assistant's own trust boundary can never be added and are ignored. Requires custom component 1.2.4 or newer."},
3537
-
sidecar_pin_port: {label: "Settings UI sidecar port",help: "0 = a new free port each restart (default); set 1024–65535 to pin a fixed port so the settings URL stays stable across restarts. Falls back to a free port if the pinned one is busy. Restart required."},
3537
+
sidecar_pin_port: {label: "Settings UI sidecar port",help: "0 picks a free port on first start and keeps it for later restarts; 1024–65535 pins a preferred port (falls back to a free one if taken). Restart required."},
3538
3538
enable_dev_mode: {label: "Developer mode",help: "⚠ DANGER: registers hidden developer tools (ha_dev_manage_server, ha_dev_manage_settings) that let AI agents change server settings and replace the running server version (e.g. install a PR build). For development and testing only. Restart required."},
3539
3539
};
3540
3540
@@ -4020,8 +4020,10 @@ loadFsCustomPaths();
4020
4020
4021
4021
// #1574 review: localStorage is the synchronous store the anti-FOUC
4022
4022
// script reads at paint time, but it is origin-scoped and the stdio
4023
-
// sidecar binds a fresh random port (= fresh empty origin) per session.
4024
-
// This hook therefore (a) mirrors every change to the server
4023
+
// sidecar's port (= the origin) can still change: stable by default
4024
+
// since #2131, yet fresh on first spawn, a lost ui.state, a pin
4025
+
// change, or a taken remembered port. This hook therefore (a) mirrors
4026
+
// every change to the server
4025
4027
// (./api/settings/theme -> theme_prefs.json), which seeds the next
4026
4028
// fresh origin via the server-prefs head script, and (b) surfaces a
4027
4029
// blocked localStorage (private mode) once instead of silently losing
0 commit comments