fix(prompt): skip bundled AGENTS.md for desktop launch cwd

This commit is contained in:
fangliquanflq
2026-08-29 05:28:20 +08:00
committed by Teknium
parent 793690a0a0
commit c6ee4e0809
6 changed files with 100 additions and 2 deletions
+9 -1
View File
@@ -892,8 +892,16 @@ def build_system_prompt_parts(agent: Any, system_message: Optional[str] = None)
# (developing Hermes). Every other surface (desktop chat panel,
# gateway daemons) self-spawns into the install tree, where the
# fallback would inject this repo's contributor AGENTS.md (#64590).
context_cwd = resolve_context_cwd()
if getattr(agent, "_context_cwd_is_launch_artifact", False):
# Desktop session creation pins the backend launch directory so
# tools have a deterministic cwd even when the user picked no
# workspace. Preserve that tool routing, but let context discovery
# see it as the fallback it really is. The install-tree guard can
# then reject Hermes's bundled contributor AGENTS.md (#97448).
context_cwd = None
context_files_prompt = _r.build_context_files_prompt(
cwd=resolve_context_cwd(), skip_soul=_soul_loaded,
cwd=context_cwd, skip_soul=_soul_loaded,
context_length=_ctx_len,
allow_install_tree_fallback=agent.platform in ("cli", "tui"),
home_override=_agent_home(agent))
+44
View File
@@ -66,6 +66,50 @@ class TestContextFileCwd:
monkeypatch.setenv("TERMINAL_CWD", str(tmp_path))
assert _captured_context_cwd(_make_agent()) == tmp_path
def test_desktop_launch_artifact_does_not_load_bundled_agents_md(
self, monkeypatch, tmp_path
):
import agent.runtime_cwd as runtime_cwd
monkeypatch.setattr(runtime_cwd, "_PACKAGE_ROOT", tmp_path.resolve())
monkeypatch.chdir(tmp_path)
(tmp_path / "AGENTS.md").write_text("bundled contributor instructions")
agent = _make_agent(
platform="desktop",
_context_cwd_is_launch_artifact=True,
)
with (
patch("run_agent.load_soul_md", return_value=""),
patch("run_agent.build_environment_hints", return_value=""),
patch("agent.system_prompt.resolve_context_cwd", return_value=tmp_path),
):
context = build_system_prompt_parts(agent)["context"]
assert "bundled contributor instructions" not in context
def test_desktop_explicit_install_tree_workspace_still_loads_agents_md(
self, monkeypatch, tmp_path
):
import agent.runtime_cwd as runtime_cwd
monkeypatch.setattr(runtime_cwd, "_PACKAGE_ROOT", tmp_path.resolve())
monkeypatch.chdir(tmp_path)
(tmp_path / "AGENTS.md").write_text("chosen workspace instructions")
agent = _make_agent(
platform="desktop",
_context_cwd_is_launch_artifact=False,
)
with (
patch("run_agent.load_soul_md", return_value=""),
patch("run_agent.build_environment_hints", return_value=""),
patch("agent.system_prompt.resolve_context_cwd", return_value=tmp_path),
):
context = build_system_prompt_parts(agent)["context"]
assert "chosen workspace instructions" in context
def _stable_prompt(agent):
with (
+15
View File
@@ -496,6 +496,21 @@ def test_desktop_launch_cwd_is_not_persisted_as_a_workspace():
) == "/picked/repo"
def test_desktop_launch_cwd_is_marked_as_context_artifact():
assert server._context_cwd_is_launch_artifact(
{"source": "desktop", "cwd": "/opt/hermes"}
) is True
def test_explicit_desktop_and_terminal_cwds_are_context_workspaces():
assert server._context_cwd_is_launch_artifact(
{"source": "desktop", "cwd": "/picked/repo", "explicit_cwd": True}
) is False
assert server._context_cwd_is_launch_artifact(
{"source": "tui", "cwd": "/opt/hermes"}
) is False
def test_home_container_dirs_are_never_a_workspace(tmp_path):
"""`/home` and `/Users` hold homes; they are not workspaces themselves.
+3
View File
@@ -573,6 +573,9 @@ class ComputeHost:
reasoning_config_override=frame.get("reasoning_config_override"),
service_tier_override=frame.get("service_tier_override"),
platform_override=frame.get("source"),
context_cwd_is_launch_artifact=bool(
frame.get("context_cwd_is_launch_artifact", False)
),
session_db=session_db,
)
if server._transfer_db_to_agent(agent, session_db):
+7
View File
@@ -945,6 +945,10 @@ def _(rid, params: dict) -> dict:
session_id=target,
session_db=db,
platform_override=source,
context_cwd_is_launch_artifact=(
source in _LAUNCH_CWD_NOT_A_WORKSPACE
and not profile_resume_cwd
),
**stored_runtime_overrides,
)
finally:
@@ -3304,6 +3308,9 @@ def _(rid, params: dict) -> dict:
session_id=new_key,
session_db=branch_db,
platform_override=source,
context_cwd_is_launch_artifact=(
_context_cwd_is_launch_artifact(session)
),
)
finally:
_clear_session_context(tokens)
+22 -1
View File
@@ -2634,6 +2634,7 @@ def _compute_host_turn_frame(
"history_version": history_version,
"cols": int(session.get("cols", 80) or 80),
"cwd": _session_cwd(session),
"context_cwd_is_launch_artifact": _context_cwd_is_launch_artifact(session),
"profile_home": session.get("profile_home") or "",
"model_override": session.get("model_override"),
"reasoning_config_override": session.get("create_reasoning_override"),
@@ -3568,6 +3569,15 @@ def _session_cwd(session: dict | None) -> str:
_LAUNCH_CWD_NOT_A_WORKSPACE = {"desktop"}
def _context_cwd_is_launch_artifact(session: dict | None) -> bool:
"""Whether the session cwd came from app launch rather than user intent."""
return bool(
session
and not session.get("explicit_cwd")
and _session_source(session) in _LAUNCH_CWD_NOT_A_WORKSPACE
)
def _persisted_session_cwd(session: dict) -> str | None:
"""The cwd to stamp on the session's DB row, or None to leave it unset.
@@ -8832,6 +8842,7 @@ def _make_agent(
reasoning_config_override: dict | None = None,
service_tier_override: str | None = None,
platform_override: str | None = None,
context_cwd_is_launch_artifact: bool | None = None,
):
# AC-4 test seam: dead unless explicitly armed by the isolated certify
# harness. Both inline and compute-host paths construct through _make_agent,
@@ -8961,7 +8972,7 @@ def _make_agent(
raise RuntimeError("Auth fallback resolved without a model")
model = resolution.selected_model
_pr = _load_provider_routing()
return AIAgent(
agent = AIAgent(
model=model,
max_iterations=_cfg_max_turns(cfg, 500),
provider=runtime.get("provider"),
@@ -9008,6 +9019,16 @@ def _make_agent(
fallback_model=_load_fallback_model(),
**_agent_cbs(sid),
)
if context_cwd_is_launch_artifact is None:
with _sessions_lock:
context_session = _sessions.get(sid)
context_cwd_is_launch_artifact = _context_cwd_is_launch_artifact(
context_session
)
agent._context_cwd_is_launch_artifact = bool(
context_cwd_is_launch_artifact
)
return agent
def _init_session(