fix(tools): profile-scoped checkpoint/snapshot paths, tool caches, TZ and schema paths under multiplex
Under `gateway.multiplex_profiles` one gateway process serves every profile
under ~/.hermes/profiles/NAME/; each routed turn runs with a context-local
HERMES_HOME override while `os.environ` still holds the DEFAULT profile's
values. Anything evaluated once at import, or memoised in a single unkeyed
module slot, therefore freezes the LAUNCH profile's value and leaks it into
every other profile's turns. This lands the tools-side half of that class:
- tools/process_registry.py, tools/environments/{modal,singularity}.py:
`_checkpoint_path()` / `_snapshot_store()` resolve `get_hermes_home()` at
call time (same seam as `tools/skills_tool._skills_dir`, so the existing
`monkeypatch.setattr(CHECKPOINT_PATH)` test sites keep working). Completes
the checkpoint_manager / sticker_cache half cherry-picked from #56315.
- plugins/platforms/feishu/feishu_comment_rules.py: `_MtimeCache` is now
path-keyed (accepts a Path or a zero-arg resolver, one (mtime, data) slot
per resolved path) with `invalidate()`; `_rules_file()` / `_pairing_file()`
resolve the routed profile's files. Proposed in #63962.
- tools/tool_output_limits.py, tools/browser_tool.py, tools/browser_camofox.py:
the process-lifetime config caches are dicts keyed by `hermes_home_key()`;
the `_X_resolved` flags and the lifecycle reset keep their shape.
tools/file_tools.py drops its private `file_read_max_chars` memo and reads
the already mtime+path-cached `load_config_readonly()`.
- hermes_time.py: `get_timezone_name()`; when `is_multiplex_active()` the
env `HERMES_TIMEZONE` (bridged from the default profile's config at gateway
startup) is ignored in favour of the routed profile's config.yaml. Both
sandbox TZ sites (code_execution_env/_tool) now use it.
- tools/cronjob_tools.py, tools/tts_tool.py, tools/skill_manager_tool.py:
the static schema text is profile-neutral and `dynamic_schema_overrides=`
rebuilds the `display_hermes_home()` / create-dir hint per
`get_definitions()`, so a routed profile's model sees its own paths.
Refs #95685.
Co-authored-by: Nathan Shan <nathanielcrush51@gmail.com>
(cherry picked from commit 6d3fc6b07b3155c6196b1fd61a829283f1d7855c)
This commit is contained in:
@@ -108,6 +108,35 @@ class TestGetTimezone:
|
||||
monkeypatch.setenv("HERMES_HOME", str(first_home))
|
||||
assert str(hermes_time.get_timezone()) == "Asia/Tokyo"
|
||||
|
||||
def test_multiplex_prefers_routed_profile_config_over_env(self, tmp_path, monkeypatch):
|
||||
"""Under the multiplexed gateway HERMES_TIMEZONE holds only the DEFAULT profile's value
|
||||
(bridged at startup), so a routed profile must resolve from its own config.yaml."""
|
||||
from agent.secret_scope import set_multiplex_active
|
||||
from hermes_constants import reset_hermes_home_override, set_hermes_home_override
|
||||
|
||||
default_home, routed_home = tmp_path / "default", tmp_path / "routed"
|
||||
default_home.mkdir()
|
||||
routed_home.mkdir()
|
||||
(default_home / "config.yaml").write_text("timezone: America/New_York\n", encoding="utf-8")
|
||||
(routed_home / "config.yaml").write_text("timezone: Asia/Tokyo\n", encoding="utf-8")
|
||||
monkeypatch.setenv("HERMES_HOME", str(default_home))
|
||||
monkeypatch.setenv("HERMES_TIMEZONE", "America/New_York")
|
||||
|
||||
# Single-profile process: env stays authoritative.
|
||||
assert hermes_time.get_timezone_name() == "America/New_York"
|
||||
|
||||
set_multiplex_active(True)
|
||||
try:
|
||||
assert hermes_time.get_timezone_name() == "America/New_York" # default profile turn
|
||||
token = set_hermes_home_override(str(routed_home))
|
||||
try:
|
||||
assert hermes_time.get_timezone_name() == "Asia/Tokyo"
|
||||
assert str(hermes_time.get_timezone()) == "Asia/Tokyo"
|
||||
finally:
|
||||
reset_hermes_home_override(token)
|
||||
finally:
|
||||
set_multiplex_active(False)
|
||||
|
||||
def test_concurrent_profile_resolution_never_mixes_zones(
|
||||
self, tmp_path, monkeypatch
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user