oclaw/tests/test_oclaw_worker_title.py
oliver 9f4fa3d319 fix(chat): harden session auto-title and keep a single no-tool LLM call
- Add session_auto_title prompts, finalize_auto_title (reject prose, truncate, fallback).
- Third-round naming: one model.chat(system, user) with empty tools; reuse executor.model.
- Extend worker title tests for garbage model output.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-06 15:19:22 +08:00

104 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import hashlib
from pathlib import Path
from oclaw.platform.persistence.sqlite_store import SqliteStore
from oclaw.runtime.types import StandardMessage
from oclaw.runtime.worker import _maybe_generate_title_on_third_round
class _DummyResp:
def __init__(self, content: str) -> None:
self.content = content
class _DummyModel:
def __init__(self, content: str = "第三轮标题") -> None:
self._content = content
def chat(self, _messages, _tools, on_token=None): # noqa: ANN001
return _DummyResp(self._content)
def test_worker_third_round_title_generation_updates_stage3(tmp_path: Path) -> None:
store = SqliteStore(str(tmp_path / "worker-title.sqlite"))
tenant = store.create_tenant("Team")
user = store.create_user_account(
tenant_id=str(tenant["id"]),
username="tester",
display_name="Tester",
role="owner",
password_hash=hashlib.sha256("test-pass".encode("utf-8")).hexdigest(),
is_active=True,
)
session = store.create_session_for_user(
title="第一轮标题",
tenant_id=str(tenant["id"]),
user_id=str(user["id"]),
)
sid = str(session.id)
store.set_setting(f"AIA_SESSION_AUTO_TITLE_STAGE:{sid}", "1")
store.add_message(session_id=sid, role="user", content="第一轮问题")
store.add_message(session_id=sid, role="assistant", content="第一轮回答")
store.add_message(session_id=sid, role="user", content="第二轮问题")
store.add_message(session_id=sid, role="assistant", content="第二轮回答")
msg = StandardMessage(
session_id=sid,
tenant_id=str(tenant["id"]),
user_id=str(user["id"]),
role="member",
channel="admin_chat",
text="第三轮问题",
attachments=[],
metadata={"lang": "zh"},
)
_maybe_generate_title_on_third_round(store=store, msg=msg, model=_DummyModel())
renamed = store.get_session(sid)
assert renamed is not None
assert str(getattr(renamed, "title", "") or "") == "第三轮标题"
assert str(store.get_setting(f"AIA_SESSION_AUTO_TITLE_STAGE:{sid}") or "") == "3"
def test_worker_third_round_rejects_prose_title_uses_fallback(tmp_path: Path) -> None:
store = SqliteStore(str(tmp_path / "worker-title-fb.sqlite"))
tenant = store.create_tenant("Team")
user = store.create_user_account(
tenant_id=str(tenant["id"]),
username="tester",
display_name="Tester",
role="owner",
password_hash=hashlib.sha256("test-pass".encode("utf-8")).hexdigest(),
is_active=True,
)
session = store.create_session_for_user(
title="第一轮标题",
tenant_id=str(tenant["id"]),
user_id=str(user["id"]),
)
sid = str(session.id)
store.set_setting(f"AIA_SESSION_AUTO_TITLE_STAGE:{sid}", "1")
store.add_message(session_id=sid, role="user", content="第一轮问题")
store.add_message(session_id=sid, role="assistant", content="第一轮回答")
store.add_message(session_id=sid, role="user", content="第二轮问题")
store.add_message(session_id=sid, role="assistant", content="第二轮回答")
msg = StandardMessage(
session_id=sid,
tenant_id=str(tenant["id"]),
user_id=str(user["id"]),
role="member",
channel="admin_chat",
text="第三轮问题",
attachments=[],
metadata={"lang": "zh"},
)
garbage = "您好!我是 Claude Code,一个软件工程助手。" + "x" * 80
_maybe_generate_title_on_third_round(store=store, msg=msg, model=_DummyModel(content=garbage))
renamed = store.get_session(sid)
assert renamed is not None
assert str(getattr(renamed, "title", "") or "") == "第一轮问题"
assert str(store.get_setting(f"AIA_SESSION_AUTO_TITLE_STAGE:{sid}") or "") == "3"