qin-chenghan a94ea9325b
fix(agents): load SOUL.md from agent dirs without config.yaml (#4136)
* fix(agents): load SOUL.md from agent dirs without config.yaml (#4135)

resolve_agent_dir requires config.yaml to be present in an agent
directory (added in #3481 to fix #3390, where memory-only directories
were mistaken for agent directories). However, SOUL.md loading does
not depend on config.yaml. When an agent is configured externally
(e.g. via DEER_FLOW_CONFIG_PATH) and the agent directory contains
SOUL.md but no config.yaml, resolve_agent_dir skips the directory
and load_agent_soul returns None.

Add a fallback in load_agent_soul: if the resolved directory does not
contain SOUL.md, check the per-user and legacy directories directly
for SOUL.md. This preserves the #3390 fix for resolve_agent_dir
(which is also used by load_agent_config) while allowing SOUL.md
to load independently of config.yaml.

* fix(agents): gate SOUL.md fallback on missing config.yaml per review

Address review feedback on PR #4136:

1. Gate the fallback condition on not (agent_dir / config.yaml).exists()
   so it only fires when resolve_agent_dir returned its default path (no
   agent dir qualified), not when a properly-resolved per-user agent simply
   lacks SOUL.md. This preserves the per-user shadowing invariant.

2. Fix test_loads_soul_from_user_dir_without_config_yaml to actually
   exercise the fallback path: per-user memory-only dir (no config.yaml,
   no SOUL.md) + legacy dir with SOUL.md (no config.yaml) -> fallback
   finds legacy SOUL.md.

3. Add test_soul_not_leaked_from_legacy_when_per_user_has_config to
   verify the gate prevents legacy SOUL.md leaking into a per-user agent.

4. Patch get_effective_user_id in test_loads_soul_without_config_yaml
   for consistency and resilience.
2026-07-13 21:13:33 +08:00
..