Merge remote-tracking branch 'sandbox/194/work' into feature/ctrlc-cancel
This commit is contained in:
@@ -161,6 +161,12 @@ std::expected<std::string, std::string> Harness::chat(const Message& user_messag
|
||||
tool_result.content = result;
|
||||
push_message(tool_result);
|
||||
}
|
||||
|
||||
if (ctrlc_request)
|
||||
// Cancellation after tool execution: same semantics as above -
|
||||
// return empty string to preserve conversation state in the chat file.
|
||||
return "";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ add_dr_test(test_tool_list_files)
|
||||
add_dr_test(test_tool_grep)
|
||||
add_dr_test(test_tool_shell)
|
||||
add_dr_test(test_tool_shell_ctrlc)
|
||||
add_dr_test(test_ctrlc_after_tool)
|
||||
add_dr_test(test_tool_read_multi_modal)
|
||||
|
||||
# Add feature validation tests
|
||||
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
# test_ctrlc_after_tool.sh - Test ctrlc (SIGINT) handling between tool calls
|
||||
|
||||
# Create mock responses: two tool calls followed by a final response
|
||||
# First tool sleeps 1 second, second tool is instant
|
||||
# We send SIGINT during the first tool's execution (at 0.5s)
|
||||
# The new ctrlc check after tool execution should catch it at 1s
|
||||
tool_call run_dangerous_shell '{"command":"sleep 1","timeout_seconds":5}' >> mock_ctrlc_between_tools.txt
|
||||
tool_call run_dangerous_shell '{"command":"echo second_tool","timeout_seconds":5}' >> mock_ctrlc_between_tools.txt
|
||||
be_done 'Final response' >> mock_ctrlc_between_tools.txt
|
||||
|
||||
# Run drharness in background
|
||||
"${DRHARNESS}" -F chat_ctrlc.json -n -m "Test ctrlc between tools" -t run_dangerous_shell -d < "mock_ctrlc_between_tools.txt" > /dev/null 2>&1 &
|
||||
DRHARNESS_PID=$!
|
||||
|
||||
# Send SIGINT at 0.5s - during first tool's sleep
|
||||
sleep 0.5
|
||||
kill -SIGINT $DRHARNESS_PID 2>/dev/null || true
|
||||
|
||||
# Wait for drharness to complete (first tool finishes at 1s, then ctrlc check catches it)
|
||||
wait $DRHARNESS_PID 2>/dev/null || true
|
||||
|
||||
# Verify the chat file exists and has the conversation state preserved
|
||||
if [ ! -f chat_ctrlc.json ]; then
|
||||
echo "FAIL: chat_ctrlc.json was not created"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check that we have exactly 3 history entries: user message, assistant tool call, tool result
|
||||
# The second tool call should NOT have executed because ctrlc was caught after first tool
|
||||
HISTORY_LENGTH=$(history_length chat_ctrlc.json)
|
||||
|
||||
if [ "$HISTORY_LENGTH" -ne 3 ]; then
|
||||
echo "FAIL: Expected exactly 3 history entries (user, assistant, tool), got $HISTORY_LENGTH"
|
||||
echo "This indicates the second tool call was not cancelled properly"
|
||||
cat chat_ctrlc.json
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify user message is present
|
||||
USER_ROLE=$(dr_role chat_ctrlc.json 0)
|
||||
if [ "$USER_ROLE" != "user" ]; then
|
||||
echo "FAIL: Expected user role at index 0, got $USER_ROLE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify assistant with tool call is present
|
||||
ASSISTANT_ROLE=$(dr_role chat_ctrlc.json 1)
|
||||
if [ "$ASSISTANT_ROLE" != "assistant" ]; then
|
||||
echo "FAIL: Expected assistant role at index 1, got $ASSISTANT_ROLE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify tool result is present
|
||||
TOOL_ROLE=$(dr_role chat_ctrlc.json 2)
|
||||
if [ "$TOOL_ROLE" != "tool" ]; then
|
||||
echo "FAIL: Expected tool role at index 2, got $TOOL_ROLE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "PASS: ctrlc_after_tool"
|
||||
Reference in New Issue
Block a user