mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-08 22:20:54 +08:00
fix(chat): compress-history on PostgreSQL dict rows
- Normalize select id,content rows from dict_row vs sqlite Row in history_tool_result_compact. - Expand memory_wiki_search ToolSpec to match wiki_search parameters; add schema regression test. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
0dc0c4663f
commit
acfb2cf73b
4 changed files with 56 additions and 4 deletions
|
|
@ -25,6 +25,13 @@ class HistoryCompactionResult:
|
|||
detail: str = ""
|
||||
|
||||
|
||||
def _chat_message_id_content(row: Any) -> tuple[int, str]:
|
||||
"""Normalize SQLite Row/tuple vs PostgreSQL dict_row for ``select id, content``."""
|
||||
if isinstance(row, dict):
|
||||
return int(row["id"]), str(row.get("content") or "")
|
||||
return int(row[0]), str(row[1] or "") # type: ignore[index]
|
||||
|
||||
|
||||
def _json_dumps_safe(obj: Any) -> str:
|
||||
try:
|
||||
return json.dumps(obj, ensure_ascii=False, default=str)
|
||||
|
|
@ -150,7 +157,8 @@ def compact_tool_results_in_session_history(
|
|||
(sid, max(1, min(int(limit_messages or 5000), 200_000))),
|
||||
)
|
||||
rows = cur.fetchall() or []
|
||||
for mid, raw in rows:
|
||||
for row in rows:
|
||||
mid, raw = _chat_message_id_content(row)
|
||||
scanned += 1
|
||||
txt = str(raw or "")
|
||||
max_seen = max(max_seen, len(txt))
|
||||
|
|
|
|||
|
|
@ -99,10 +99,27 @@ def _search_tool(public_name: str, desc: str) -> ToolSpec:
|
|||
parameters={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {"type": "string"},
|
||||
"limit": {"type": "integer"},
|
||||
"query": {"type": "string", "description": "Search query string."},
|
||||
"limit": {"type": "integer", "description": "Max hits per page (server caps to wiki max)."},
|
||||
"offset": {"type": "integer", "description": "Hit offset for pagination (0-based)."},
|
||||
"context_lines": {
|
||||
"type": "integer",
|
||||
"description": "Lines of context around each match (server caps at 5).",
|
||||
},
|
||||
"is_regex": {"type": "boolean"},
|
||||
"case_sensitive": {"type": "boolean"},
|
||||
"path_prefix": {
|
||||
"type": "string",
|
||||
"description": "Only search under this relative path prefix (e.g. users/).",
|
||||
},
|
||||
"expand_query": {
|
||||
"type": "boolean",
|
||||
"description": "If true, try synonym-expanded variants (ignored when is_regex is true).",
|
||||
},
|
||||
"max_rounds": {
|
||||
"type": "integer",
|
||||
"description": "Max expansion rounds when expand_query is true (1–5).",
|
||||
},
|
||||
},
|
||||
"required": ["query"],
|
||||
"additionalProperties": False,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,18 @@ from __future__ import annotations
|
|||
import json
|
||||
|
||||
from svc.persistence.sqlite_store import SqliteStore
|
||||
from runtime.chat.history_tool_result_compact import compact_tool_results_in_session_history
|
||||
from runtime.chat.history_tool_result_compact import (
|
||||
_chat_message_id_content,
|
||||
compact_tool_results_in_session_history,
|
||||
)
|
||||
|
||||
|
||||
def test_chat_message_id_content_dict_row() -> None:
|
||||
assert _chat_message_id_content({"id": 42, "content": "hello"}) == (42, "hello")
|
||||
|
||||
|
||||
def test_chat_message_id_content_tuple_like() -> None:
|
||||
assert _chat_message_id_content((9, "z")) == (9, "z")
|
||||
|
||||
|
||||
def test_compact_tool_results_in_session_history_rewrites_large_tool_message(tmp_path) -> None: # noqa: ANN001
|
||||
|
|
|
|||
|
|
@ -12,6 +12,22 @@ from runtime.tools.public.memory_wiki_tools import (
|
|||
)
|
||||
|
||||
|
||||
def test_memory_wiki_search_tool_schema_exposes_wiki_search_args() -> None:
|
||||
props = memory_wiki_search_tool().parameters.get("properties") or {}
|
||||
for key in (
|
||||
"query",
|
||||
"limit",
|
||||
"offset",
|
||||
"context_lines",
|
||||
"is_regex",
|
||||
"case_sensitive",
|
||||
"path_prefix",
|
||||
"expand_query",
|
||||
"max_rounds",
|
||||
):
|
||||
assert key in props, f"missing schema property: {key}"
|
||||
|
||||
|
||||
def test_memory_wiki_tools_handlers_load_without_dataclass_module_error() -> None:
|
||||
status = memory_wiki_status_tool().handler({})
|
||||
assert isinstance(status, dict)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue