oclaw/tests/test_memory_wiki_search_api.py
oliver 420abac9f1 refactor: root-package imports (svc/runtime/interfaces) and fix PYTHONPATH
- Rename platform/ to svc/ to avoid shadowing stdlib platform.
- Replace from oclaw.* with from svc/runtime/interfaces; update -m CLI paths.
- tests/conftest: prepend repo root to sys.path (no parent-folder package name).
- CI: paths and offline_eval script under repo root.
- Ops scripts: PYTHONPATH must be repo root for python -m runtime.* (fixes gateway/WhatsApp sidecar startup).
- Fix default oclaw.json path in tabular/file attachment limits; stabilize attachment test config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 14:51:17 +08:00

98 lines
3.5 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 importlib.util
from pathlib import Path
import sys
from types import SimpleNamespace
from svc.config.paths import PROJECT_ROOT
def _wiki_search_handler(tmp_path: Path):
api_path = (PROJECT_ROOT / "runtime" / "extensions" / "memory-wiki" / "api.py").resolve()
spec = importlib.util.spec_from_file_location("memory_wiki_api_test", str(api_path))
assert spec is not None and spec.loader is not None
mod = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = mod
spec.loader.exec_module(mod) # type: ignore[assignment]
wiki_root = tmp_path / "wiki"
wiki_root.mkdir(parents=True, exist_ok=True)
rows = mod.build_wiki_tool_specs(
SimpleNamespace(plugin_config={"wiki_root": str(wiki_root), "max_search_results": 10, "max_get_lines": 200})
)
for r in rows:
if str(r.get("name") or "") == "wiki_search":
return wiki_root, r["handler"]
raise AssertionError("wiki_search handler missing")
def test_wiki_search_returns_context_and_pagination_metadata(tmp_path: Path) -> None:
wiki_root, handler = _wiki_search_handler(tmp_path)
p = wiki_root / "users" / "identity.md"
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(
"\n".join(
[
"# Identity",
"creator is Oliver",
"project owner is Oliver",
"session profile line",
]
),
encoding="utf-8",
)
out = handler({"query": "Oliver", "limit": 1, "offset": 0, "context_lines": 1})
assert out.get("ok") is True
assert out.get("query") == "Oliver"
assert out.get("truncated") is True
assert out.get("next_offset") == 1
hits = out.get("hits") or []
assert len(hits) == 1
hit = hits[0]
assert hit.get("path") == "users/identity.md"
assert isinstance(hit.get("before"), list)
assert isinstance(hit.get("after"), list)
assert "matched_query" in hit
def test_wiki_search_offset_paginates_deterministically(tmp_path: Path) -> None:
wiki_root, handler = _wiki_search_handler(tmp_path)
p = wiki_root / "identity.md"
p.write_text("Oliver one\nOliver two\nOliver three\n", encoding="utf-8")
page1 = handler({"query": "Oliver", "limit": 2, "offset": 0})
page2 = handler({"query": "Oliver", "limit": 2, "offset": 2})
hits1 = page1.get("hits") or []
hits2 = page2.get("hits") or []
assert [h.get("line") for h in hits1] == [1, 2]
assert [h.get("line") for h in hits2] == [3]
assert page2.get("truncated") is False
assert page2.get("next_offset") is None
def test_wiki_search_expand_query_reports_attempted_queries(tmp_path: Path) -> None:
wiki_root, handler = _wiki_search_handler(tmp_path)
p = wiki_root / "users" / "identity.md"
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text("项目所有者:Oliver\n", encoding="utf-8")
out = handler({"query": "用户", "expand_query": True, "max_rounds": 3, "limit": 5})
assert out.get("ok") is True
attempted = out.get("queries_attempted") or []
assert attempted
assert attempted[0] == "用户"
assert len(attempted) <= 3
hits = out.get("hits") or []
assert hits
assert any(h.get("matched_query") != "用户" for h in hits)
def test_wiki_search_keeps_backward_compatible_keys(tmp_path: Path) -> None:
wiki_root, handler = _wiki_search_handler(tmp_path)
(wiki_root / "a.md").write_text("hello\n", encoding="utf-8")
out = handler({"query": "hello"})
assert {"ok", "query", "hits", "truncated"}.issubset(set(out.keys()))