From d3b5c563ce4fe440bacd1b4f0257e498ceeff316 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sun, 7 Jun 2026 20:18:29 +0000 Subject: [PATCH] fix(extract): disable tools for digest LLM extraction (no error_max_turns) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit חילוץ-המטא-דאטה של יומון הוא טקסט→JSON טהור, אבל ה-claude CLI רץ עם tools זמינים, ו-Sonnet לפעמים פולט stop_reason=tool_use → פוגע ב---max-turns 1 → error_max_turns → retry (איטי). מבזבז זמן רב בגיבוי-המוני. - claude_session.query/query_json: פרמטר חדש `tools` → מועבר כ---tools. "" = ביטוי כל ה-tools (אין tool_use → אין max-turns trip). None = ברירת-CLI. - digest_metadata_extractor.extract: מעביר tools="". אומת: extract על יומון 5160 ב-Sonnet+tools="" → num_turns=1, JSON תקין, ללא error_max_turns. claude_session נשאר local-only. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/legal_mcp/services/claude_session.py | 15 +++++++++++++-- .../services/digest_metadata_extractor.py | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/mcp-server/src/legal_mcp/services/claude_session.py b/mcp-server/src/legal_mcp/services/claude_session.py index f6b077b..668d230 100644 --- a/mcp-server/src/legal_mcp/services/claude_session.py +++ b/mcp-server/src/legal_mcp/services/claude_session.py @@ -82,6 +82,7 @@ async def query( system: str | None = None, model: str | None = None, effort: str | None = None, + tools: str | None = None, ) -> str: """Send a prompt to Claude Code headless and return the text response. @@ -104,6 +105,12 @@ async def query( effort: Optional effort level (``low``/``medium``/``high``/``xhigh``/ ``max``). When set, passed as ``--effort``. Pairs with ``model``; an empty string is treated as "unset" (CLI default). + tools: Optional available-tools spec, passed as ``--tools``. Pass an + empty string (``""``) to disable ALL tools — for pure text→JSON + extraction the model has no reason to call a tool, and leaving + tools enabled makes it occasionally emit ``stop_reason: tool_use`` + which trips ``--max-turns 1`` → ``error_max_turns`` and forces a + retry (slow). ``None`` leaves the CLI default (all tools). Returns: The text response from Claude. @@ -126,6 +133,8 @@ async def query( cmd += ["--model", model] if effort: cmd += ["--effort", effort] + if tools is not None: # "" → disable all tools (no tool_use → no max-turns trip) + cmd += ["--tools", tools] size_info = f"; prompt_len={len(full_prompt):,} chars" if len(full_prompt) > 100_000 else "" last_err = "unknown error" @@ -204,13 +213,15 @@ async def query_json( system: str | None = None, model: str | None = None, effort: str | None = None, + tools: str | None = None, ) -> dict | list | None: """Send a prompt and parse the response as JSON. Uses parse_llm_json for robust parsing (handles markdown wrapping, truncation). - ``model``/``effort`` are forwarded to :func:`query` (see its docstring). + ``model``/``effort``/``tools`` are forwarded to :func:`query` (see its docstring). + Pure text→JSON extractors should pass ``tools=""`` to avoid ``error_max_turns``. """ - raw = await query(prompt, timeout=timeout, system=system, model=model, effort=effort) + raw = await query(prompt, timeout=timeout, system=system, model=model, effort=effort, tools=tools) return parse_llm_json(raw) diff --git a/mcp-server/src/legal_mcp/services/digest_metadata_extractor.py b/mcp-server/src/legal_mcp/services/digest_metadata_extractor.py index 6745439..48cb52b 100644 --- a/mcp-server/src/legal_mcp/services/digest_metadata_extractor.py +++ b/mcp-server/src/legal_mcp/services/digest_metadata_extractor.py @@ -101,6 +101,8 @@ async def extract(raw_text: str, model: str | None = None) -> dict: result = await claude_session.query_json( user_msg, system=DIGEST_EXTRACTION_PROMPT, model=(model or config.DIGEST_EXTRACT_MODEL or None), + tools="", # pure text→JSON: disable tools so the model never emits + # stop_reason=tool_use and trips --max-turns (error_max_turns). ) except Exception as e: # surfaced as warning, not swallowed silently (§6) logger.warning("digest_metadata_extractor: query failed: %s", e)