统一会话展示与专家路由行为,修复图片异步显示与气泡宽度问题。

本次移除 image 专家角色并同步更新路由/绑定/测试,同时增强 session-bootstrap 的共享与角色分层记忆加载,减少刷新依赖并提升默认可用性。

Made-with: Cursor
This commit is contained in:
oliver 2026-04-29 22:16:49 +08:00
parent 1ebfa47dd3
commit d5e30542aa
19 changed files with 199 additions and 62 deletions

View file

@ -225,7 +225,7 @@ def test_gateway_comprehensive_mode_manager_first_selects_specialist(monkeypatch
class _ManagerModel:
def chat(self, _messages, _tools, *, on_token=None):
return LLMResponse(
content='{"route":{"specialist":"image","reason":"needs image edits"},"dispatch":{"instruction_text":"Please edit the image background."}}',
content='{"route":{"specialist":"generalist","reason":"needs image edits"},"dispatch":{"instruction_text":"Please edit the image background."}}',
tool_calls=[],
)
@ -239,8 +239,8 @@ def test_gateway_comprehensive_mode_manager_first_selects_specialist(monkeypatch
"oclaw.runtime.gateway.get_manager_prompt_prebuild",
lambda **kwargs: {
"manager_context": "manager",
"allowed_fixed": ("generalist", "ops", "image", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "image", "memory"',
"allowed_fixed": ("generalist", "ops", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "memory"',
},
)
captured: dict = {}
@ -272,8 +272,8 @@ def test_gateway_comprehensive_mode_manager_first_selects_specialist(monkeypatch
)
out = gw.handle_turn(msg=msg, lang="en", executor=_Exec(model=_ManagerModel()), specialist_executor_factory=_factory)
assert out.interaction_mode == "comprehensive"
assert out.selected_specialist == "image"
assert chosen.get("sid") == "image"
assert out.selected_specialist == "generalist"
assert chosen.get("sid") == "generalist"
assert captured.get("exec_text") == "Please edit the image background."
assert captured.get("persisted_user_text") == "edit this image background"
@ -308,8 +308,8 @@ def test_gateway_comprehensive_mode_writes_task_assignment_reasoning(monkeypatch
"oclaw.runtime.gateway.get_manager_prompt_prebuild",
lambda **kwargs: {
"manager_context": "manager",
"allowed_fixed": ("generalist", "ops", "image", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "image", "memory"',
"allowed_fixed": ("generalist", "ops", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "memory"',
},
)
monkeypatch.setattr(
@ -367,8 +367,8 @@ def test_gateway_comprehensive_ignores_wiki_inject_flags(monkeypatch: pytest.Mon
"oclaw.runtime.gateway.get_manager_prompt_prebuild",
lambda **kwargs: {
"manager_context": "manager",
"allowed_fixed": ("generalist", "ops", "image", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "image", "memory"',
"allowed_fixed": ("generalist", "ops", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "memory"',
},
)
captured: dict[str, object] = {}
@ -430,8 +430,8 @@ def test_gateway_comprehensive_mode_has_manager_final_pass(monkeypatch: pytest.M
"oclaw.runtime.gateway.get_manager_prompt_prebuild",
lambda **kwargs: {
"manager_context": "manager",
"allowed_fixed": ("generalist", "ops", "image", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "image", "memory"',
"allowed_fixed": ("generalist", "ops", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "memory"',
},
)
monkeypatch.setattr(
@ -486,8 +486,8 @@ def test_gateway_comprehensive_mode_dynamic_agent_dispatches_instruction_only(mo
"oclaw.runtime.gateway.get_manager_prompt_prebuild",
lambda **kwargs: {
"manager_context": "manager",
"allowed_fixed": ("generalist", "ops", "image", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "image", "memory"',
"allowed_fixed": ("generalist", "ops", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "memory"',
},
)
monkeypatch.setattr("oclaw.runtime.gateway.build_ephemeral_executor", lambda *args, **kwargs: _Exec(model=object()))
@ -549,8 +549,8 @@ def test_gateway_comprehensive_mode_ignores_manager_self_and_dispatches_speciali
"oclaw.runtime.gateway.get_manager_prompt_prebuild",
lambda **kwargs: {
"manager_context": "manager",
"allowed_fixed": ("generalist", "ops", "image", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "image", "memory"',
"allowed_fixed": ("generalist", "ops", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "memory"',
},
)
@ -626,8 +626,8 @@ def test_gateway_comprehensive_mode_suppresses_instruction_echo(monkeypatch: pyt
"oclaw.runtime.gateway.get_manager_prompt_prebuild",
lambda **kwargs: {
"manager_context": "manager",
"allowed_fixed": ("generalist", "ops", "image", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "image", "memory"',
"allowed_fixed": ("generalist", "ops", "memory"),
"allowed_fixed_quoted": '"generalist", "ops", "memory"',
},
)

View file

@ -6,7 +6,5 @@ from oclaw.runtime.agents.specialists import default_system_prefix_for_specialis
def test_specialist_prompts_loaded_from_oclaw_tree() -> None:
ops = default_system_prefix_for_specialist("ops", "zh")
gen = default_system_prefix_for_specialist("generalist", "zh")
img = default_system_prefix_for_specialist("image", "zh")
assert "运维专家(ops specialist)" in ops
assert "通识专家(generalist specialist)" in gen
assert "图像专家(image specialist)" in img

View file

@ -106,7 +106,7 @@ def test_interaction_mode_normalization_supports_legacy_values() -> None:
def test_requested_specialist_normalization_defaults_to_generalist() -> None:
assert normalize_requested_specialist("ops") == "ops"
assert normalize_requested_specialist("image") == "image"
assert normalize_requested_specialist("image") == "generalist"
assert normalize_requested_specialist("memory") == "memory"
assert normalize_requested_specialist("unknown") == "generalist"

View file

@ -14,7 +14,7 @@ class _DummyStore:
def test_get_manager_prompt_prebuild_includes_structured_skills(monkeypatch) -> None:
monkeypatch.setattr(pp, "discover_specialist_ids", lambda: ("generalist", "ops", "image", "memory"))
monkeypatch.setattr(pp, "discover_specialist_ids", lambda: ("generalist", "ops", "memory"))
monkeypatch.setattr(
pp,
"list_experts",

View file

@ -18,4 +18,3 @@ def test_agent_role_ids_uses_runtime_discovery(monkeypatch) -> None:
def test_builtin_specialists_include_memory_tools() -> None:
assert "memory" in specialists_mod.expert_name_for_specialist("generalist")
assert "memory" in specialists_mod.expert_name_for_specialist("ops")
assert "memory" in specialists_mod.expert_name_for_specialist("image")