Преглед изворни кода

Simplify message processing to match amq2api reference

Key changes:
1. Remove global seen_tool_result_ids tracking in process_history
   - This was causing tool_results to be incorrectly skipped
   - amq2api reference doesn't have this logic
2. Simplify merge_user_messages in message_processor.py
   - Remove complex toolResults deduplication
   - Just preserve first message's context as-is
   - Match amq2api's simpler approach

The complex deduplication logic was causing issues when Claude Code
sends multiple parallel tool calls - the model was getting confused
by the modified history.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
jerry-271828 пре 1 месец
родитељ
комит
de23eb94c5
2 измењених фајлова са 3 додато и 77 уклоњено
  1. 0 12
      claude_converter.py
  2. 3 65
      message_processor.py

+ 0 - 12
claude_converter.py

@@ -328,13 +328,9 @@ def process_history(messages: List[ClaudeMessage], thinking_enabled: bool = Fals
     Dual-mode detection:
     Dual-mode detection:
     - If messages already alternate correctly (no consecutive user/assistant), skip merging
     - If messages already alternate correctly (no consecutive user/assistant), skip merging
     - If messages have consecutive same-role messages, apply merge logic
     - If messages have consecutive same-role messages, apply merge logic
-
-    Key fix: Track seen_tool_result_ids across ALL messages to prevent duplicate tool_results
-    that cause infinite loops where the model keeps responding to the same user message.
     """
     """
     history = []
     history = []
     seen_tool_use_ids = set()  # Track tool_use IDs in assistant messages
     seen_tool_use_ids = set()  # Track tool_use IDs in assistant messages
-    seen_tool_result_ids = set()  # Track tool_result IDs across ALL user messages
 
 
     raw_history = []
     raw_history = []
 
 
@@ -358,10 +354,6 @@ def process_history(messages: List[ClaudeMessage], thinking_enabled: bool = Fals
                             text_parts.append(_wrap_thinking_content(block.get("thinking", "")))
                             text_parts.append(_wrap_thinking_content(block.get("thinking", "")))
                         elif btype == "tool_result":
                         elif btype == "tool_result":
                             tool_use_id = block.get("tool_use_id")
                             tool_use_id = block.get("tool_use_id")
-                            # Skip if this tool_result was already processed in a previous message
-                            if tool_use_id and tool_use_id in seen_tool_result_ids:
-                                logger.debug(f"Skipping duplicate tool_result across messages: {tool_use_id}")
-                                continue
 
 
                             if tool_results is None:
                             if tool_results is None:
                                 tool_results = []
                                 tool_results = []
@@ -374,10 +366,6 @@ def process_history(messages: List[ClaudeMessage], thinking_enabled: bool = Fals
                                     existing["status"] = "error"
                                     existing["status"] = "error"
                             else:
                             else:
                                 tool_results.append(result)
                                 tool_results.append(result)
-
-                            # Mark as processed globally
-                            if tool_use_id:
-                                seen_tool_result_ids.add(tool_use_id)
                 text_content = "\n".join(text_parts)
                 text_content = "\n".join(text_parts)
             else:
             else:
                 text_content = extract_text_from_content(content)
                 text_content = extract_text_from_content(content)

+ 3 - 65
message_processor.py

@@ -12,13 +12,6 @@ def merge_user_messages(user_messages: List[Dict[str, Any]]) -> Dict[str, Any]:
     """
     """
     合并多个 userInputMessage 的内容
     合并多个 userInputMessage 的内容
 
 
-    IMPORTANT: This function properly merges toolResults from all messages to prevent
-    losing tool execution history, which would cause infinite loops where the model
-    keeps responding to the same user message.
-
-    Key fix: Deduplicate toolResults by toolUseId to prevent duplicate tool_result
-    entries that cause the model to repeatedly respond to the same user message.
-
     Args:
     Args:
         user_messages: userInputMessage 列表
         user_messages: userInputMessage 列表
 
 
@@ -33,30 +26,19 @@ def merge_user_messages(user_messages: List[Dict[str, Any]]) -> Dict[str, Any]:
     base_context = None
     base_context = None
     base_origin = None
     base_origin = None
     base_model = None
     base_model = None
-    # Use dict to deduplicate toolResults by toolUseId
-    tool_results_by_id: Dict[str, Dict[str, Any]] = {}
     all_images = []  # Collect images from messages
     all_images = []  # Collect images from messages
 
 
     for msg in user_messages:
     for msg in user_messages:
         content = msg.get("content", "")
         content = msg.get("content", "")
         msg_ctx = msg.get("userInputMessageContext", {})
         msg_ctx = msg.get("userInputMessageContext", {})
 
 
-        # Initialize base context from first message
+        # 保留第一个消息的上下文信息
         if base_context is None:
         if base_context is None:
             base_context = msg_ctx.copy() if msg_ctx else {}
             base_context = msg_ctx.copy() if msg_ctx else {}
-            # Remove toolResults from base to merge them separately
-            if "toolResults" in base_context:
-                for tr in base_context.pop("toolResults"):
-                    _merge_tool_result(tool_results_by_id, tr)
-        else:
-            # Collect toolResults from subsequent messages
-            if "toolResults" in msg_ctx:
-                for tr in msg_ctx["toolResults"]:
-                    _merge_tool_result(tool_results_by_id, tr)
 
 
         # 保留第一个消息的 origin
         # 保留第一个消息的 origin
         if base_origin is None:
         if base_origin is None:
-            base_origin = msg.get("origin", "CLI")
+            base_origin = msg.get("origin", "KIRO_CLI")
 
 
         # 保留第一个消息的 modelId
         # 保留第一个消息的 modelId
         if base_model is None and "modelId" in msg:
         if base_model is None and "modelId" in msg:
@@ -78,13 +60,9 @@ def merge_user_messages(user_messages: List[Dict[str, Any]]) -> Dict[str, Any]:
     merged_msg = {
     merged_msg = {
         "content": merged_content,
         "content": merged_content,
         "userInputMessageContext": base_context or {},
         "userInputMessageContext": base_context or {},
-        "origin": base_origin or "CLI"
+        "origin": base_origin or "KIRO_CLI"
     }
     }
 
 
-    # Add deduplicated toolResults if any
-    if tool_results_by_id:
-        merged_msg["userInputMessageContext"]["toolResults"] = list(tool_results_by_id.values())
-
     # 如果原始消息有 modelId,也保留
     # 如果原始消息有 modelId,也保留
     if base_model:
     if base_model:
         merged_msg["modelId"] = base_model
         merged_msg["modelId"] = base_model
@@ -100,46 +78,6 @@ def merge_user_messages(user_messages: List[Dict[str, Any]]) -> Dict[str, Any]:
     return merged_msg
     return merged_msg
 
 
 
 
-def _merge_tool_result(tool_results_by_id: Dict[str, Dict[str, Any]], tool_result: Dict[str, Any]) -> None:
-    """
-    Merge a tool_result into the deduplicated dict.
-    If toolUseId already exists, merge the content arrays.
-
-    Args:
-        tool_results_by_id: Dict mapping toolUseId to tool_result
-        tool_result: The tool_result to merge
-    """
-    tool_use_id = tool_result.get("toolUseId")
-    if not tool_use_id:
-        return
-
-    if tool_use_id in tool_results_by_id:
-        # Merge content arrays
-        existing = tool_results_by_id[tool_use_id]
-        existing_content = existing.get("content", [])
-        new_content = tool_result.get("content", [])
-
-        # Deduplicate content by text value
-        existing_texts = {item.get("text", "") for item in existing_content if isinstance(item, dict)}
-        for item in new_content:
-            if isinstance(item, dict):
-                text = item.get("text", "")
-                if text and text not in existing_texts:
-                    existing_content.append(item)
-                    existing_texts.add(text)
-
-        existing["content"] = existing_content
-
-        # If any result has error status, keep error
-        if tool_result.get("status") == "error":
-            existing["status"] = "error"
-
-        logger.debug(f"Merged duplicate toolUseId {tool_use_id}")
-    else:
-        # New toolUseId, add to dict
-        tool_results_by_id[tool_use_id] = tool_result.copy()
-
-
 def process_claude_history_for_amazonq(history: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
 def process_claude_history_for_amazonq(history: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
     """
     """
     处理 Claude Code 历史记录,使其符合 Amazon Q 要求
     处理 Claude Code 历史记录,使其符合 Amazon Q 要求