diff --git a/agent/prompt_builder.py b/agent/prompt_builder.py index 83c8eb13ff..e33569f051 100644 --- a/agent/prompt_builder.py +++ b/agent/prompt_builder.py @@ -12,7 +12,7 @@ import threading from collections import OrderedDict from pathlib import Path -from hermes_constants import get_hermes_home, get_skills_dir +from hermes_constants import get_hermes_home, get_skills_dir, is_wsl from typing import Optional from agent.skill_utils import ( @@ -366,6 +366,36 @@ PLATFORM_HINTS = { ), } +# --------------------------------------------------------------------------- +# Environment hints — execution-environment awareness for the agent. +# Unlike PLATFORM_HINTS (which describe the messaging channel), these describe +# the machine/OS the agent's tools actually run on. +# --------------------------------------------------------------------------- + +WSL_ENVIRONMENT_HINT = ( + "You are running inside WSL (Windows Subsystem for Linux). " + "The Windows host filesystem is mounted under /mnt/ — " + "/mnt/c/ is the C: drive, /mnt/d/ is D:, etc. " + "The user's Windows files are typically at " + "/mnt/c/Users//Desktop/, Documents/, Downloads/, etc. " + "When the user references Windows paths or desktop files, translate " + "to the /mnt/c/ equivalent. You can list /mnt/c/Users/ to discover " + "the Windows username if needed." +) + + +def build_environment_hints() -> str: + """Return environment-specific guidance for the system prompt. + + Detects WSL, and can be extended for Termux, Docker, etc. + Returns an empty string when no special environment is detected. + """ + hints: list[str] = [] + if is_wsl(): + hints.append(WSL_ENVIRONMENT_HINT) + return "\n\n".join(hints) + + CONTEXT_FILE_MAX_CHARS = 20_000 CONTEXT_TRUNCATE_HEAD_RATIO = 0.7 CONTEXT_TRUNCATE_TAIL_RATIO = 0.2 diff --git a/run_agent.py b/run_agent.py index 01863a0a14..333dda3927 100644 --- a/run_agent.py +++ b/run_agent.py @@ -94,7 +94,7 @@ from agent.model_metadata import ( from agent.context_compressor import ContextCompressor from agent.subdirectory_hints import SubdirectoryHintTracker from agent.prompt_caching import apply_anthropic_cache_control -from agent.prompt_builder import build_skills_system_prompt, build_context_files_prompt, load_soul_md, TOOL_USE_ENFORCEMENT_GUIDANCE, TOOL_USE_ENFORCEMENT_MODELS, DEVELOPER_ROLE_MODELS, GOOGLE_MODEL_OPERATIONAL_GUIDANCE, OPENAI_MODEL_EXECUTION_GUIDANCE +from agent.prompt_builder import build_skills_system_prompt, build_context_files_prompt, build_environment_hints, load_soul_md, TOOL_USE_ENFORCEMENT_GUIDANCE, TOOL_USE_ENFORCEMENT_MODELS, DEVELOPER_ROLE_MODELS, GOOGLE_MODEL_OPERATIONAL_GUIDANCE, OPENAI_MODEL_EXECUTION_GUIDANCE from agent.usage_pricing import estimate_usage_cost, normalize_usage from agent.display import ( KawaiiSpinner, build_tool_preview as _build_tool_preview, @@ -3193,6 +3193,12 @@ class AIAgent: f"not on any model name returned by the API." ) + # Environment hints (WSL, Termux, etc.) — tell the agent about the + # execution environment so it can translate paths and adapt behavior. + _env_hints = build_environment_hints() + if _env_hints: + prompt_parts.append(_env_hints) + platform_key = (self.platform or "").lower().strip() if platform_key in PLATFORM_HINTS: prompt_parts.append(PLATFORM_HINTS[platform_key]) diff --git a/tests/agent/test_prompt_builder.py b/tests/agent/test_prompt_builder.py index 1f2f6ada77..5a222cc38b 100644 --- a/tests/agent/test_prompt_builder.py +++ b/tests/agent/test_prompt_builder.py @@ -18,6 +18,7 @@ from agent.prompt_builder import ( build_skills_system_prompt, build_nous_subscription_prompt, build_context_files_prompt, + build_environment_hints, CONTEXT_FILE_MAX_CHARS, DEFAULT_AGENT_IDENTITY, TOOL_USE_ENFORCEMENT_GUIDANCE, @@ -26,6 +27,7 @@ from agent.prompt_builder import ( MEMORY_GUIDANCE, SESSION_SEARCH_GUIDANCE, PLATFORM_HINTS, + WSL_ENVIRONMENT_HINT, ) from hermes_cli.nous_subscription import NousFeatureState, NousSubscriptionFeatures @@ -770,6 +772,29 @@ class TestPromptBuilderConstants: assert "cli" in PLATFORM_HINTS +# ========================================================================= +# Environment hints +# ========================================================================= + +class TestEnvironmentHints: + def test_wsl_hint_constant_mentions_mnt(self): + assert "/mnt/c/" in WSL_ENVIRONMENT_HINT + assert "WSL" in WSL_ENVIRONMENT_HINT + + def test_build_environment_hints_on_wsl(self, monkeypatch): + import agent.prompt_builder as _pb + monkeypatch.setattr(_pb, "is_wsl", lambda: True) + result = _pb.build_environment_hints() + assert "/mnt/" in result + assert "WSL" in result + + def test_build_environment_hints_not_wsl(self, monkeypatch): + import agent.prompt_builder as _pb + monkeypatch.setattr(_pb, "is_wsl", lambda: False) + result = _pb.build_environment_hints() + assert result == "" + + # ========================================================================= # Conditional skill activation # =========================================================================