Fix tool_use/tool_result validation to check ALL messages
Browse files- Previous fix only checked last message
- Now validates entire conversation for proper tool_use→tool_result pairs
- Skips any assistant message with tool_use that lacks following tool_result
- Dockerfile +1 -1
- chainlit_app.py +2 -2
- codepilot/llm/claude_client.py +40 -9
Dockerfile
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
# HuggingFace Spaces Dockerfile for CodePilot
|
| 2 |
-
# BUILD_VERSION:
|
| 3 |
FROM python:3.11-slim
|
| 4 |
|
| 5 |
# Set working directory
|
|
|
|
| 1 |
# HuggingFace Spaces Dockerfile for CodePilot
|
| 2 |
+
# BUILD_VERSION: 16 (v3.3.7 validate-all - validate all messages for tool_use/result pairs)
|
| 3 |
FROM python:3.11-slim
|
| 4 |
|
| 5 |
# Set working directory
|
chainlit_app.py
CHANGED
|
@@ -20,8 +20,8 @@ from concurrent.futures import ThreadPoolExecutor
|
|
| 20 |
# ============================================================
|
| 21 |
# STARTUP VERSION CHECK - Change this to detect if rebuild worked
|
| 22 |
# ============================================================
|
| 23 |
-
APP_VERSION = "3.3.
|
| 24 |
-
BUILD_ID = "2024-12-19-
|
| 25 |
print("=" * 60)
|
| 26 |
print(f"[STARTUP] CodePilot Chainlit App")
|
| 27 |
print(f"[STARTUP] APP_VERSION: {APP_VERSION}")
|
|
|
|
| 20 |
# ============================================================
|
| 21 |
# STARTUP VERSION CHECK - Change this to detect if rebuild worked
|
| 22 |
# ============================================================
|
| 23 |
+
APP_VERSION = "3.3.7-validate-all"
|
| 24 |
+
BUILD_ID = "2024-12-19-v15"
|
| 25 |
print("=" * 60)
|
| 26 |
print(f"[STARTUP] CodePilot Chainlit App")
|
| 27 |
print(f"[STARTUP] APP_VERSION: {APP_VERSION}")
|
codepilot/llm/claude_client.py
CHANGED
|
@@ -122,21 +122,52 @@ class ClaudeClient:
|
|
| 122 |
"content": pending_tool_results
|
| 123 |
})
|
| 124 |
|
| 125 |
-
# BUGFIX: Validate
|
| 126 |
# Claude API requires tool_result immediately after tool_use
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
if isinstance(content, list):
|
| 132 |
has_tool_use = any(
|
| 133 |
isinstance(b, dict) and b.get("type") == "tool_use"
|
| 134 |
for b in content
|
| 135 |
)
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
|
| 141 |
# Build request parameters
|
| 142 |
request_params = {
|
|
|
|
| 122 |
"content": pending_tool_results
|
| 123 |
})
|
| 124 |
|
| 125 |
+
# BUGFIX: Validate ALL messages - each tool_use must have tool_result after
|
| 126 |
# Claude API requires tool_result immediately after tool_use
|
| 127 |
+
validated_messages = []
|
| 128 |
+
i = 0
|
| 129 |
+
while i < len(conversation_messages):
|
| 130 |
+
msg = conversation_messages[i]
|
| 131 |
+
|
| 132 |
+
# Check if this is an assistant message with tool_use
|
| 133 |
+
if msg.get("role") == "assistant":
|
| 134 |
+
content = msg.get("content", [])
|
| 135 |
+
has_tool_use = False
|
| 136 |
if isinstance(content, list):
|
| 137 |
has_tool_use = any(
|
| 138 |
isinstance(b, dict) and b.get("type") == "tool_use"
|
| 139 |
for b in content
|
| 140 |
)
|
| 141 |
+
|
| 142 |
+
if has_tool_use:
|
| 143 |
+
# Check if next message has tool_result
|
| 144 |
+
if i + 1 < len(conversation_messages):
|
| 145 |
+
next_msg = conversation_messages[i + 1]
|
| 146 |
+
next_content = next_msg.get("content", [])
|
| 147 |
+
has_tool_result = False
|
| 148 |
+
if isinstance(next_content, list):
|
| 149 |
+
has_tool_result = any(
|
| 150 |
+
isinstance(b, dict) and b.get("type") == "tool_result"
|
| 151 |
+
for b in next_content
|
| 152 |
+
)
|
| 153 |
+
|
| 154 |
+
if has_tool_result:
|
| 155 |
+
# Valid pair - add both
|
| 156 |
+
validated_messages.append(msg)
|
| 157 |
+
validated_messages.append(next_msg)
|
| 158 |
+
i += 2
|
| 159 |
+
continue
|
| 160 |
+
|
| 161 |
+
# No valid tool_result - skip this tool_use message
|
| 162 |
+
print(f"[CLAUDE] Warning: Skipping assistant message with tool_use (no tool_result follows)")
|
| 163 |
+
i += 1
|
| 164 |
+
continue
|
| 165 |
+
|
| 166 |
+
# Regular message - add it
|
| 167 |
+
validated_messages.append(msg)
|
| 168 |
+
i += 1
|
| 169 |
+
|
| 170 |
+
conversation_messages = validated_messages
|
| 171 |
|
| 172 |
# Build request parameters
|
| 173 |
request_params = {
|