hermes-font-scale 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LUKE
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,147 @@
1
+ Metadata-Version: 2.4
2
+ Name: hermes-font-scale
3
+ Version: 0.1.1
4
+ Summary: Unofficial community helper — make Hermes Desktop GUI font bigger in one command.
5
+ Author: LUKE
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/hsukevin0407-crypto/hermes-font-scale
8
+ Project-URL: Issues, https://github.com/hsukevin0407-crypto/hermes-font-scale/issues
9
+ Keywords: hermes-agent,cli,accessibility,font-size,electron
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: End Users/Desktop
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Dynamic: license-file
26
+
27
+ # 🐍 hermes-font-scale
28
+
29
+ > Unofficial community helper — patch **Hermes Desktop GUI** font size in one command, atomically and reversibly.
30
+ > NOT affiliated with [NousResearch/hermes-agent](https://github.com/NousResearch/hermes-agent).
31
+
32
+ ![Tests](https://img.shields.io/github/actions/workflow/status/hsukevin0407-crypto/hermes-font-scale/test.yml?branch=main&label=tests)
33
+ ![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)
34
+ ![License](https://img.shields.io/github/license/hsukevin0407-crypto/hermes-font-scale)
35
+ ![Version](https://img.shields.io/github/v/release/hsukevin0407-crypto/hermes-font-scale)
36
+
37
+ ---
38
+
39
+ ## ✨ Features
40
+
41
+ - **Atomic font patch** — rewrites only the `html { font-size: clamp(...) }` line; crash-safe via temp-file + `os.replace()`
42
+ - **Reversible** — `reset` restores from an auto-created `.bak`; `set` is idempotent and skips unnecessary writes
43
+ - **Zero runtime deps** — stdlib only; works on Python 3.9–3.12 across Windows / macOS / Linux
44
+ - **Multi-OS path resolution** — auto-detects Hermes install from `HERMES_HOME`, env var, or 10+ known install paths
45
+ - **Diagnostic `doctor` command** — 4-check health report pinpoints the exact failure before you patch
46
+
47
+ ---
48
+
49
+ ## 🚀 Getting Started
50
+
51
+ ### Prerequisites
52
+
53
+ - Python >= 3.9
54
+
55
+ ### Installation
56
+
57
+ Currently available from source only (PyPI publication pending):
58
+
59
+ ```bash
60
+ pip install "git+https://github.com/hsukevin0407-crypto/hermes-font-scale.git@v0.1.1"
61
+ ```
62
+
63
+ Or clone and install locally:
64
+
65
+ ```bash
66
+ git clone https://github.com/hsukevin0407-crypto/hermes-font-scale.git
67
+ cd hermes-font-scale
68
+ pip install -e .
69
+ ```
70
+
71
+ ### Usage
72
+
73
+ ```bash
74
+ # Check current state (run this first)
75
+ hermes-font-scale status
76
+
77
+ # Set base font size (10–32 px; responsive max is auto-computed)
78
+ hermes-font-scale set 18
79
+
80
+ # Preview without writing anything
81
+ hermes-font-scale set 18 --dry-run
82
+
83
+ # Run the 4-check diagnostic
84
+ hermes-font-scale doctor
85
+
86
+ # Restore the original CSS from the .bak file
87
+ hermes-font-scale reset
88
+
89
+ # Machine-readable output
90
+ hermes-font-scale status --json
91
+ ```
92
+
93
+ After `set`, **restart Hermes Desktop** to see the change.
94
+
95
+ ---
96
+
97
+ ## 🏗️ Architecture
98
+
99
+ ```mermaid
100
+ graph LR
101
+ A[CLI: hermes-font-scale] --> B{Command}
102
+ B -->|set N| C[Locate globals.css]
103
+ B -->|reset| D[Restore from .bak]
104
+ B -->|status| E[Read current value]
105
+ B -->|doctor| F[4-check diagnostic]
106
+ C --> G[Atomic rewrite via os.replace]
107
+ G --> H[globals.css patched]
108
+ ```
109
+
110
+ Hermes Desktop hard-codes font size in one CSS anchor:
111
+
112
+ ```css
113
+ /* node_modules/@nous-research/ui/dist/ui/globals.css */
114
+ html {
115
+ font-size: clamp(14px, calc(14px + 2 * ((100vw - 1400px) / 400)), 18px);
116
+ }
117
+ ```
118
+
119
+ `hermes-font-scale set N` rewrites the two numeric bounds to `N` and `N+4`, preserving responsive behavior. Everything else in the file is untouched.
120
+
121
+ **Compatibility note:** the official Hermes Desktop installer may bundle `node_modules` inside `app.asar`. Run `hermes-font-scale doctor` — if the "font-size clause present" check fails because the file is inside an ASAR archive, see the [open issue](https://github.com/hsukevin0407-crypto/hermes-font-scale/issues) for workarounds.
122
+
123
+ ---
124
+
125
+ ## 🤝 Contributing
126
+
127
+ Pull requests are welcome. For major changes, please open an issue first.
128
+
129
+ ```bash
130
+ # Run tests
131
+ pip install pytest pytest-cov
132
+ pytest
133
+
134
+ # Lint
135
+ pip install ruff
136
+ ruff check src tests
137
+ ```
138
+
139
+ CI runs on Python 3.9, 3.10, 3.11, 3.12 across Ubuntu / Windows / macOS.
140
+
141
+ ## 📄 License
142
+
143
+ [MIT](LICENSE)
144
+
145
+ ---
146
+
147
+ > **Disclaimer:** Unofficial community project. Not affiliated with or endorsed by Nous Research. Use at your own risk.
@@ -0,0 +1,121 @@
1
+ # 🐍 hermes-font-scale
2
+
3
+ > Unofficial community helper — patch **Hermes Desktop GUI** font size in one command, atomically and reversibly.
4
+ > NOT affiliated with [NousResearch/hermes-agent](https://github.com/NousResearch/hermes-agent).
5
+
6
+ ![Tests](https://img.shields.io/github/actions/workflow/status/hsukevin0407-crypto/hermes-font-scale/test.yml?branch=main&label=tests)
7
+ ![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)
8
+ ![License](https://img.shields.io/github/license/hsukevin0407-crypto/hermes-font-scale)
9
+ ![Version](https://img.shields.io/github/v/release/hsukevin0407-crypto/hermes-font-scale)
10
+
11
+ ---
12
+
13
+ ## ✨ Features
14
+
15
+ - **Atomic font patch** — rewrites only the `html { font-size: clamp(...) }` line; crash-safe via temp-file + `os.replace()`
16
+ - **Reversible** — `reset` restores from an auto-created `.bak`; `set` is idempotent and skips unnecessary writes
17
+ - **Zero runtime deps** — stdlib only; works on Python 3.9–3.12 across Windows / macOS / Linux
18
+ - **Multi-OS path resolution** — auto-detects Hermes install from `HERMES_HOME`, env var, or 10+ known install paths
19
+ - **Diagnostic `doctor` command** — 4-check health report pinpoints the exact failure before you patch
20
+
21
+ ---
22
+
23
+ ## 🚀 Getting Started
24
+
25
+ ### Prerequisites
26
+
27
+ - Python >= 3.9
28
+
29
+ ### Installation
30
+
31
+ Currently available from source only (PyPI publication pending):
32
+
33
+ ```bash
34
+ pip install "git+https://github.com/hsukevin0407-crypto/hermes-font-scale.git@v0.1.1"
35
+ ```
36
+
37
+ Or clone and install locally:
38
+
39
+ ```bash
40
+ git clone https://github.com/hsukevin0407-crypto/hermes-font-scale.git
41
+ cd hermes-font-scale
42
+ pip install -e .
43
+ ```
44
+
45
+ ### Usage
46
+
47
+ ```bash
48
+ # Check current state (run this first)
49
+ hermes-font-scale status
50
+
51
+ # Set base font size (10–32 px; responsive max is auto-computed)
52
+ hermes-font-scale set 18
53
+
54
+ # Preview without writing anything
55
+ hermes-font-scale set 18 --dry-run
56
+
57
+ # Run the 4-check diagnostic
58
+ hermes-font-scale doctor
59
+
60
+ # Restore the original CSS from the .bak file
61
+ hermes-font-scale reset
62
+
63
+ # Machine-readable output
64
+ hermes-font-scale status --json
65
+ ```
66
+
67
+ After `set`, **restart Hermes Desktop** to see the change.
68
+
69
+ ---
70
+
71
+ ## 🏗️ Architecture
72
+
73
+ ```mermaid
74
+ graph LR
75
+ A[CLI: hermes-font-scale] --> B{Command}
76
+ B -->|set N| C[Locate globals.css]
77
+ B -->|reset| D[Restore from .bak]
78
+ B -->|status| E[Read current value]
79
+ B -->|doctor| F[4-check diagnostic]
80
+ C --> G[Atomic rewrite via os.replace]
81
+ G --> H[globals.css patched]
82
+ ```
83
+
84
+ Hermes Desktop hard-codes font size in one CSS anchor:
85
+
86
+ ```css
87
+ /* node_modules/@nous-research/ui/dist/ui/globals.css */
88
+ html {
89
+ font-size: clamp(14px, calc(14px + 2 * ((100vw - 1400px) / 400)), 18px);
90
+ }
91
+ ```
92
+
93
+ `hermes-font-scale set N` rewrites the two numeric bounds to `N` and `N+4`, preserving responsive behavior. Everything else in the file is untouched.
94
+
95
+ **Compatibility note:** the official Hermes Desktop installer may bundle `node_modules` inside `app.asar`. Run `hermes-font-scale doctor` — if the "font-size clause present" check fails because the file is inside an ASAR archive, see the [open issue](https://github.com/hsukevin0407-crypto/hermes-font-scale/issues) for workarounds.
96
+
97
+ ---
98
+
99
+ ## 🤝 Contributing
100
+
101
+ Pull requests are welcome. For major changes, please open an issue first.
102
+
103
+ ```bash
104
+ # Run tests
105
+ pip install pytest pytest-cov
106
+ pytest
107
+
108
+ # Lint
109
+ pip install ruff
110
+ ruff check src tests
111
+ ```
112
+
113
+ CI runs on Python 3.9, 3.10, 3.11, 3.12 across Ubuntu / Windows / macOS.
114
+
115
+ ## 📄 License
116
+
117
+ [MIT](LICENSE)
118
+
119
+ ---
120
+
121
+ > **Disclaimer:** Unofficial community project. Not affiliated with or endorsed by Nous Research. Use at your own risk.
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "hermes-font-scale"
7
+ version = "0.1.1"
8
+ description = "Unofficial community helper — make Hermes Desktop GUI font bigger in one command."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "LUKE" }]
13
+ keywords = ["hermes-agent", "cli", "accessibility", "font-size", "electron"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Console",
17
+ "Intended Audience :: End Users/Desktop",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Utilities",
27
+ ]
28
+ # Intentionally zero runtime deps — stdlib only.
29
+ dependencies = []
30
+
31
+ [project.scripts]
32
+ hermes-font-scale = "hermes_font_scale.cli:main"
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/hsukevin0407-crypto/hermes-font-scale"
36
+ Issues = "https://github.com/hsukevin0407-crypto/hermes-font-scale/issues"
37
+
38
+ [tool.setuptools.packages.find]
39
+ where = ["src"]
40
+
41
+ [tool.setuptools.package-data]
42
+ hermes_font_scale = ["py.typed"]
43
+
44
+ [tool.pytest.ini_options]
45
+ minversion = "7.0"
46
+ testpaths = ["tests"]
47
+ addopts = "-v --tb=short"
48
+
49
+ [tool.ruff]
50
+ line-length = 100
51
+ target-version = "py39"
52
+
53
+ [tool.ruff.lint]
54
+ select = ["E", "F", "W", "I", "B", "UP"]
55
+ ignore = ["E501"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ """hermes-font-scale: Unofficial community helper for Hermes Desktop font size.
2
+
3
+ Public API:
4
+ CLI entry point: ``hermes-font-scale`` (see cli.main)
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from .constants import VERSION
10
+
11
+ __version__ = VERSION
12
+ __all__ = ["__version__"]
@@ -0,0 +1,8 @@
1
+ """Entry point so ``python -m hermes_font_scale`` works."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .cli import main
6
+
7
+ if __name__ == "__main__":
8
+ raise SystemExit(main())
@@ -0,0 +1,190 @@
1
+ """Command-line interface for hermes-font-scale.
2
+
3
+ Subcommands:
4
+ set <PX> set font size (10..32)
5
+ reset restore from .bak
6
+ status print current state
7
+ doctor run 4 diagnostic checks
8
+
9
+ Common flags:
10
+ --hermes-home PATH override install root
11
+ --dry-run show what would happen without writing
12
+ --json machine-readable output for status
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import argparse
18
+ import json
19
+ import os
20
+ import sys
21
+ from pathlib import Path
22
+
23
+ # On Windows, the default console codepage is often cp1252 which chokes on
24
+ # the non-ASCII strings we use in messages. Reconfigure stdout/stderr to
25
+ # UTF-8 so help text and error messages don't crash the CLI.
26
+ #
27
+ # Skip this when running under pytest — capsys replaces stdout/stderr
28
+ # and reconfigure() breaks the capture machinery.
29
+ if os.name == "nt" and not os.environ.get("PYTEST_CURRENT_TEST"):
30
+ try:
31
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace") # type: ignore[attr-defined]
32
+ sys.stderr.reconfigure(encoding="utf-8", errors="replace") # type: ignore[attr-defined]
33
+ except (AttributeError, OSError):
34
+ pass
35
+
36
+ from . import __version__
37
+ from . import doctor as doctor_mod
38
+ from . import scale as scale_mod
39
+ from .constants import MAX_PX, MIN_PX
40
+ from .locate import HermesNotFound, locate_globals_css, _display_path
41
+
42
+
43
+ def _build_parser() -> argparse.ArgumentParser:
44
+ parser = argparse.ArgumentParser(
45
+ prog="hermes-font-scale",
46
+ description=(
47
+ "Unofficial community helper — make Hermes Desktop GUI font "
48
+ "bigger in one command. NOT part of NousResearch/hermes-agent."
49
+ ),
50
+ )
51
+ parser.add_argument(
52
+ "--version",
53
+ action="version",
54
+ version=f"hermes-font-scale {__version__}",
55
+ )
56
+ parser.add_argument(
57
+ "--hermes-home",
58
+ type=Path,
59
+ default=None,
60
+ help="Path to Hermes install root (overrides HERMES_HOME and search).",
61
+ )
62
+
63
+ sub = parser.add_subparsers(dest="command", required=True)
64
+
65
+ p_set = sub.add_parser("set", help=f"Set font size in px (range {MIN_PX}..{MAX_PX}).")
66
+ p_set.add_argument("px", type=int, help=f"Target base font size in px ({MIN_PX}..{MAX_PX}).")
67
+ p_set.add_argument(
68
+ "--dry-run",
69
+ action="store_true",
70
+ help="Show diff without writing anything.",
71
+ )
72
+
73
+ sub.add_parser("reset", help="Restore globals.css from the .bak file (if any).")
74
+
75
+ p_status = sub.add_parser("status", help="Show current patch state.")
76
+ p_status.add_argument("--json", action="store_true", help="Print JSON instead of text.")
77
+
78
+ sub.add_parser("doctor", help="Run 4 diagnostic checks.")
79
+
80
+ return parser
81
+
82
+
83
+ def _resolve_css(args: argparse.Namespace) -> Path:
84
+ try:
85
+ return locate_globals_css(hermes_home=args.hermes_home)
86
+ except HermesNotFound as exc:
87
+ print(str(exc), file=sys.stderr)
88
+ raise SystemExit(2)
89
+
90
+
91
+ def cmd_set(args: argparse.Namespace) -> int:
92
+ css = _resolve_css(args)
93
+ try:
94
+ if args.dry_run:
95
+ before, after = scale_mod.diff_lines(css, args.px)
96
+ print(f"--- {css}")
97
+ print(f"- {before}")
98
+ print(f"+ {after}")
99
+ print("(dry run — no changes written)")
100
+ return 0
101
+
102
+ result = scale_mod.patch_css(css, args.px, dry_run=False)
103
+ if result.old_base == result.new_base:
104
+ print(f"already at {result.new_base}px — nothing to do")
105
+ return 0
106
+ backup_note = " (backup created)" if result.backup_created else ""
107
+ print(
108
+ f"patched {css.name}: "
109
+ f"{result.old_base}px → {result.new_base}px{backup_note}\n"
110
+ f"restart Hermes Desktop to see the change."
111
+ )
112
+ return 0
113
+ except scale_mod.FontSizeOutOfRange as exc:
114
+ print(f"error: {exc}", file=sys.stderr)
115
+ return 2
116
+ except scale_mod.FontSizeClauseNotFound as exc:
117
+ print(f"error: {exc}", file=sys.stderr)
118
+ return 3
119
+ except PermissionError as exc:
120
+ print(f"error: {exc}", file=sys.stderr)
121
+ return 4
122
+
123
+
124
+ def cmd_reset(args: argparse.Namespace) -> int:
125
+ css = _resolve_css(args)
126
+ if scale_mod.reset_css(css):
127
+ print(f"restored {css.name} from backup. restart Hermes Desktop.")
128
+ return 0
129
+ print(f"no backup found at {css.name}.bak — nothing to restore.")
130
+ return 1
131
+
132
+
133
+ def cmd_status(args: argparse.Namespace) -> int:
134
+ try:
135
+ css = locate_globals_css(hermes_home=args.hermes_home)
136
+ except HermesNotFound as exc:
137
+ if args.json:
138
+ print(json.dumps({"ok": False, "error": str(exc)}))
139
+ else:
140
+ print(str(exc), file=sys.stderr)
141
+ return 2
142
+
143
+ base = scale_mod.read_current_base(css)
144
+ backup = css.with_name(css.name + ".bak")
145
+ payload = {
146
+ "ok": True,
147
+ "css_path": _display_path(css),
148
+ "current_base_px": base,
149
+ "backup_exists": backup.exists(),
150
+ }
151
+ if args.json:
152
+ print(json.dumps(payload, indent=2))
153
+ else:
154
+ print(f"css: {payload['css_path']}")
155
+ print(f"current base: {payload['current_base_px']}px")
156
+ print(f"backup: {'yes' if payload['backup_exists'] else 'no'}")
157
+ return 0
158
+
159
+
160
+ def cmd_doctor(args: argparse.Namespace) -> int:
161
+ css = None
162
+ try:
163
+ css = locate_globals_css(hermes_home=args.hermes_home)
164
+ except HermesNotFound:
165
+ # doctor must still report something useful when locate fails.
166
+ pass
167
+
168
+ results = doctor_mod.run_all(css)
169
+ for r in results:
170
+ print(r.render())
171
+ return 0 if doctor_mod.all_passed(results) else 1
172
+
173
+
174
+ def main(argv: list[str] | None = None) -> int:
175
+ parser = _build_parser()
176
+ args = parser.parse_args(argv)
177
+ if args.command == "set":
178
+ return cmd_set(args)
179
+ if args.command == "reset":
180
+ return cmd_reset(args)
181
+ if args.command == "status":
182
+ return cmd_status(args)
183
+ if args.command == "doctor":
184
+ return cmd_doctor(args)
185
+ parser.error(f"unknown command: {args.command}")
186
+ return 2 # unreachable, but keeps type-checkers happy
187
+
188
+
189
+ if __name__ == "__main__":
190
+ raise SystemExit(main())
@@ -0,0 +1,99 @@
1
+ """Constants for hermes-font-scale.
2
+
3
+ Single source of truth for paths, ranges, and supported versions.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from pathlib import Path
9
+
10
+ __all__ = [
11
+ "VERSION",
12
+ "MIN_PX",
13
+ "MAX_PX",
14
+ "DEFAULT_BASE_PX",
15
+ "PX_DELTA_MAX",
16
+ "FONT_SIZE_REGEX",
17
+ "REPLACEMENT_TEMPLATE",
18
+ "BACKUP_SUFFIX",
19
+ "SUPPORTED_HERMES_MAJOR",
20
+ "CSS_RELATIVE_PATH_COMPONENTS",
21
+ "WINDOWS_SEARCH_PATHS",
22
+ "MACOS_SEARCH_PATHS",
23
+ "LINUX_SEARCH_PATHS",
24
+ ]
25
+
26
+ VERSION = "0.1.1"
27
+
28
+ # Font size range (px). Outside this range we reject with a clear error.
29
+ MIN_PX = 10
30
+ MAX_PX = 32
31
+
32
+ # Original Hermes base font size (line 379 of globals.css).
33
+ DEFAULT_BASE_PX = 14
34
+
35
+ # Original max-min delta (18 - 14 = 4). We preserve this so the responsive
36
+ # scaling behavior remains identical, just shifted.
37
+ PX_DELTA_MAX = 4
38
+
39
+ # Regex matching the exact font-size clause from Hermes Desktop's globals.css.
40
+ # Captures: (1) base px, (2) unused (the calc body), (3) max px.
41
+ FONT_SIZE_REGEX = (
42
+ r"font-size\s*:\s*clamp\(\s*(\d+)px\s*,\s*"
43
+ r"calc\(\s*\d+px\s*\+\s*2\s*\*\s*\(\(100vw\s*-\s*1400px\)\s*/\s*400\)\s*\)\s*,\s*"
44
+ r"(\d+)px\s*\)"
45
+ )
46
+
47
+ # Replacement template. Caller fills {base} and {max}.
48
+ REPLACEMENT_TEMPLATE = "font-size: clamp({base}px, calc({base}px + 2 * ((100vw - 1400px) / 400)), {max}px)"
49
+
50
+ BACKUP_SUFFIX = ".bak"
51
+
52
+ # Minimum Hermes major version we support (the @nous-research/ui package
53
+ # was extracted around this version).
54
+ SUPPORTED_HERMES_MAJOR = 1
55
+
56
+ # Relative path components from Hermes install root to globals.css.
57
+ # Each entry is a candidate (some installs unpack @nous-research/ui, others don't).
58
+ CSS_RELATIVE_CANDIDATES: list[tuple[str, ...]] = [
59
+ # Production installer (asar unpacked)
60
+ (
61
+ "resources", "app.asar.unpacked", "node_modules",
62
+ "@nous-research", "ui", "dist", "ui", "globals.css",
63
+ ),
64
+ # Dev checkout
65
+ (
66
+ "apps", "desktop", "node_modules",
67
+ "@nous-research", "ui", "dist", "ui", "globals.css",
68
+ ),
69
+ # Top-level dev checkout (monorepo root)
70
+ (
71
+ "node_modules", "@nous-research", "ui", "dist", "ui", "globals.css",
72
+ ),
73
+ ]
74
+
75
+
76
+ def _join(*parts: str) -> Path:
77
+ return Path(*parts)
78
+
79
+
80
+ # Windows search roots (relative to known locations).
81
+ WINDOWS_SEARCH_ROOTS: list[Path] = [
82
+ Path.home() / "AppData" / "Local" / "hermes",
83
+ Path("C:") / "Program Files" / "Hermes",
84
+ Path("C:") / "Program Files (x86)" / "Hermes",
85
+ ]
86
+
87
+ # macOS search roots.
88
+ MACOS_SEARCH_ROOTS: list[Path] = [
89
+ Path("/Applications/Hermes.app/Contents/Resources"),
90
+ Path.home() / "Applications" / "Hermes.app" / "Contents" / "Resources",
91
+ ]
92
+
93
+ # Linux search roots.
94
+ LINUX_SEARCH_ROOTS: list[Path] = [
95
+ Path.home() / ".local" / "share" / "hermes",
96
+ Path("/opt/hermes"),
97
+ Path("/usr/local/share/hermes"),
98
+ Path("/usr/share/hermes"),
99
+ ]