Test verifies that sending SIGINT during tool execution stops processing
after that tool completes and prevents subsequent tool calls from running.
Conversation state is preserved in the chat file.
Test verifies that when SIGINT (Ctrl+C) is sent to drharness during
shell command execution, the tool returns the expected
'[user requested halt of program]' message.
- Added dr_config_base_url and dr_config_model helper functions to run_test.sh
- Updated test_harness_config.sh to use be_done() and helper functions instead of inline JSON
- Added base_url and model fields to HarnessConfig in json_types.hpp
- Removed base_url and model from OllamaConfig in ollama_client.hpp
- Updated OllamaClient constructor to accept base_url and model as separate parameters
- Updated main.cpp to use HarnessConfig for base_url and model
- Updated agent_tool.cpp to use new OllamaClient constructor
- Added test_harness_config.sh to verify the new config fields
- Updated README.md to document the config fields
Implement issue 185: Create a new flag -P that reads the prompt from a
file instead of the command line.
Changes:
- Add -P flag parsing in main.cpp
- Read prompt content from specified file
- Update help message
- Update README.md documentation
- Add test_prompt_file.sh with tests for basic, multi-line, and error cases
Resolved merge conflicts:
- CMakeLists.txt: Added both rebase_engine/utility and base64_util sources
- src/harness.cpp: Combined Content type with proper error handling
- src/main.cpp: Merged includes, test flags, and CLI parsing
- Renamed conflicting flags: -B→-Z (build_rebase), -T→-W (edit_prompt), -b→-K (base64_decode)
- tests/CMakeLists.txt: Added all test targets from both branches
- src/rebase_engine.cpp: Fixed to use get_content_string() for Content variant type
- Updated test files to use new flag names (-Z, -W, -K)
The print_history function (used by -p flag) now properly displays multimodal
content by:
- Displaying text content parts from ContentPart arrays
- Indicating presence of image_url content parts with [Image] marker
- Rendering mixed content types in a human-readable format
All 35 tests pass.
- Add test_tool_read_multi_modal.sh with tests for:
- Successfully reading a PNG image file
- Error handling for non-existent files
- Reading a JPG file (different MIME type)
- Fix json_types.hpp to properly serialize std::optional and std::variant
types by adding serialize_to_json() helper function that dispatches to
the correct serialization method.
- Register new test in tests/CMakeLists.txt
Add helper functions to run_test.sh:
- dr_history_role: Get message role from chat history
- dr_content_type: Get content type (string/array)
- dr_content_part_type: Get content part type
- dr_content_part_text: Get text from content part
- dr_content_part_image_url: Get image URL from content part
- dr_content_part_image_detail: Get image detail from content part
- dr_content_parts_count: Get content parts count
- dr_content_text: Get text content for text-only messages
Update test_multimodal_message.sh to use the new helpers instead of raw jq
Issue 156 requires verifying that chat files containing multimodal messages
can be serialized to disk and deserialized correctly when resuming a session.
This commit adds test_multimodal_roundtrip.sh which validates:
- Chat file with multimodal message contains content as array of ContentPart objects
- Chat file with text-only message contains content as string
- Resuming with -F correctly deserializes multimodal messages
- Resuming with -F correctly deserializes text-only messages
- Round-trip serialization preserves all ContentPart data
- Image data URIs are preserved in the chat file
- Mixed content types (multimodal and text-only) in same history
When -i flags are present, construct a multimodal message by combining
the text prompt and encoded images into a vector of ContentPart. The text
becomes a text content part and each image becomes an image_url content part.
Changes:
- Added overloaded chat(const Message&) method to Harness class
- Modified Harness::chat(const std::string&) to delegate to new method
- Updated main.cpp to construct multimodal message when images are present
- Added integration test test_multimodal_message.sh
Acceptance criteria met:
- When -i is used, Message::content is a vector<ContentPart>
- Text prompt is included as a text ContentPart
- Each image is included as an image_url ContentPart
- Backward compatible: when -i is not used, content is a plain string
- Works with -m, -d, -t, and -M flags
- Integration test verifies correct multimodal format in chat.json
- Add ImageUrl struct with url and detail fields
- Extend ContentPart with optional text and image_url fields
- Add std::optional serialization/deserialization support
- Custom to_json for ContentPart that only serializes relevant fields
- Custom json_to<ContentPart> for proper deserialization
- Add test_image_url.sh with comprehensive tests
- All 30 tests pass
- Added read_image_as_data_uri() function to base64_util for reading,
validating, and base64-encoding image files
- Added -i CLI flag to accept image file paths (multiple allowed)
- Added -I debug flag for testing image file reading
- Image files are validated at startup with clear error messages for
missing or unreadable files
- Updated help text and README.md documentation
- Added test_image_flag.sh with tests for PNG, JPEG, GIF formats,
error cases, and multiple -i flags
- Add base64_encode() function to encode binary data to base64 string
- Add base64_decode() function to decode base64 string to binary data
- Add get_mime_type_from_extension() for MIME type detection based on file extension
- Add generate_data_uri() for data URI prefix generation
- Add test flags -B (encode), -b (decode), -T (mime type), -U (data URI)
- Add comprehensive tests in test_base64_encode.sh
- No new dependencies added
- Add #include <variant> header
- Add json_type_for_type() helper for type-based disambiguation
- Add to_json for std::variant that serializes active alternative
- Add variant_try_helper_impl for recursive variant deserialization
- Add json_to_impl specialization for std::variant
- Add TestVariantType (std::variant<std::string, std::vector<FunctionCall>>)
for testing variant serialization
- Register TestVariantType in json_dispatch_map for -R debug flag
- Add compile-time static_assert for TestVariantType
- Add test_json_variant.sh test suite
- Add test to CMakeLists.txt
- Update ollama_client.cpp to use std::expected pattern for parse_json_safely
- Add missing 'index' field to tool_calls in add_message_field helper
- Add missing 'index' field to test_edit_history_assistant_with_tool_calls test data
- Create api_response() helper function as single point for generating
complete API response JSON structure
- Refactor tool_call(), tool_call_raw(), be_done(), reasoning_step(),
and reasoning_content_step() to use the shared api_response() function
- Export api_response function for use in test scripts
The create_state function now accepts role/content pairs as arguments
and generates the JSON internally using jq for proper escaping. This
centralizes all JSON blob generation in run_test.sh, eliminating the
need for test files to manually construct JSON arrays.
Centralize history JSON blob generation by moving the create_state
function from test_editor.sh to run_test.sh. This ensures all history
JSON generation happens in only one spot (run_test.sh).
- Added create_state function to run_test.sh with export
- Removed duplicate create_state definition from test_editor.sh
The add_message_field function now constructs tool call JSON internally
from simple parameters (id, name, arguments) instead of accepting raw
JSON strings. This makes the test helper functions more robust and
easier to use.
Changed:
- add_message_field: tool_call field now takes id, name, args and builds JSON
- create_message_json: updated to handle tool_call's 3-parameter syntax
- create_messages_json: updated to handle tool_call's 3-parameter syntax
- is_message_field: changed tool_calls to tool_call
- Updated all test files that used the old tool_calls raw JSON syntax
The file was split into 12 individual test files in a previous
commit, but the original combined file was not deleted. This
commit removes the now-obsolete test_rebase_content.sh file.
Updated all 12 test_rebase_content_* test files to use the
create_messages_json helper function from run_test.sh instead of
manually creating JSON strings, following the pattern established
by test_rebase_apply_* tests.
This complies with CONTRIBUTING.md which states:
'If you do any json handling in the test files your changes will be rejected'
All 83 tests pass.
Each test in tests/test_rebase_content.sh is now its own test script:
- test_rebase_content_basic_messages.sh
- test_rebase_content_multiline_content.sh
- test_rebase_content_tool_call_display.sh
- test_rebase_content_tool_message.sh
- test_rebase_content_empty_message.sh
- test_rebase_content_header_comments.sh
- test_rebase_content_multiple_tool_calls.sh
- test_rebase_content_message_indices.sh
- test_rebase_content_scissors_line.sh
- test_rebase_content_special_characters.sh
- test_rebase_content_unicode_characters.sh
- test_rebase_content_very_long_content.sh
All 83 tests pass.
- Consolidated dr_* functions into dr_field helper
- Refactored create_chat_file to use create_history_json
- Refactored create_rebase_lines to use create_rebase_line
- Created add_message_field helper for message field handling
- Created is_message_field helper for field name checking
- Refactored create_messages_json to use create_message_json
- Added local variable declarations for better scoping
Replace hardcoded /tmp/drharness_output.txt with $TEST_TEMP_DIR/drharness_output.txt
in all test files. Tests should only write to subfiles/directories of the working
directory (which is already a temp directory created by run_test.sh).
Add helper functions to run_test.sh for creating rebase lines and history
messages:
- create_rebase_line: creates a single rebase line JSON object
- create_rebase_lines: creates a JSON array of rebase lines
- create_message_json: creates a message JSON with optional fields
- create_messages_json: creates a JSON array of messages
Update test_rebase_apply.sh to use these helper functions instead of
manually constructing JSON strings, which violates CONTRIBUTING.md.
Split the monolithic test_edit_prompt.sh into 6 individual test files:
- test_edit_prompt_with_context.sh
- test_edit_prompt_first_message.sh
- test_edit_prompt_separator_placement.sh
- test_edit_prompt_multiline_context.sh
- test_edit_prompt_tool_role.sh
- test_edit_prompt_middle_message.sh
Each test is now its own script that can be run independently.
Add create_history_json() helper function to run_test.sh and use it in
test_edit_prompt.sh to avoid manual JSON string construction. This follows
CONTRIBUTING.md guidelines that prohibit JSON handling in test files.
Split the monolithic test_edit_history.sh file into 21 individual
test scripts, each containing a single test. This follows the
project's testing guideline of having no more than one test per script.
Each test file contains its own helper functions (run_drharness,
get_output, reset_editor_state) and runs independently.
Updated CMakeLists.txt to register all 21 new test targets and
removed the old test_edit_history target.
- Modified parse_rebase_file to skip header comments before '-- >8 --'
- Modified apply_rebase to drop messages whose indices are not mentioned
in the parsed commands (implicit drop)
- Special case: if no commands are parsed (all lines deleted), keep all messages
- Updated test_implicit_pick to reflect new behavior
- Added test_deleting_lines_drops_messages and test_all_lines_deleted_keeps_all
- Updated test_delete_line_equals_drop to reflect new behavior
- Removed the errors vector from parse_rebase_file()
- Changed all error handling to return std::unexpected() immediately
- Removed the error aggregation code at the end of the function
- Updated test to verify first error is returned (not all errors)
This refactors the duplicated code for deserializing HarnessState from a file
into a reusable helper function. The same pattern was used in two places:
1. In the edit_history block
2. In the main flow when loading existing chat files
The helper function handles:
- Opening the file
- Reading file content
- Parsing JSON
- Converting to HarnessState
- Error reporting
This reduces code duplication and makes future modifications easier.
- Add test for editing a message and removing all content (empty content)
- Add test for multiple consecutive edits to the same message (changes stack)
- Add test for editing messages with special characters
- Add test for very long message content
- Add test for editing assistant messages with tool_calls
- Add test for dropping all messages (empty history result)
- Add test for unicode characters in message content
- Add test for whitespace variations in rebase file
- Add test for comments and empty lines mixed with commands
- Add test for special characters and unicode in rebase content display
- Fix apply_rebase to preserve original content when only role is changed
- Add content_edited flag to RebaseLine to track explicit edits