Auto-generate temp file with -n flag

- Added UUID v4 generation using <random> and <filesystem> headers
- When -n is specified without -F, create a temp file in system temp dir
- Temp file is named harness-<uuid>.json
- Print temp file path to stderr when session exits
- Updated help message to reflect new behavior
- Added test_auto_temp_file.sh to verify:
  - Temp file creation with -n alone
  - Path printed to stderr
  - Existing -F <file> -n behavior preserved
  - UUID uniqueness
This commit is contained in:
2026-05-21 16:36:49 -05:00
parent 20dd58e6d4
commit 44db144bfb
3 changed files with 123 additions and 2 deletions
+60 -2
View File
@@ -18,9 +18,12 @@
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <filesystem>
#include <random>
#include <iomanip>
static const std::vector<AgentProfile> profiles = {
#if !defined(_WIN32)
@@ -39,6 +42,36 @@ static const std::vector<std::string> default_tools =
{
};
// UUID v4 generation using <random> and <filesystem> only
static std::string generate_uuid() {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 15);
std::uniform_int_distribution<> dis2(8, 11); // for variant bits
std::ostringstream ss;
for (int i = 0; i < 8; i++) {
ss << std::hex << dis(gen);
}
ss << "-";
for (int i = 0; i < 4; i++) {
ss << std::hex << dis(gen);
}
ss << "-4"; // version 4
for (int i = 0; i < 3; i++) {
ss << std::hex << dis(gen);
}
ss << "-";
ss << std::hex << dis2(gen);
for (int i = 0; i < 3; i++) {
ss << std::hex << dis(gen);
}
ss << "-";
for (int i = 0; i < 12; i++) {
ss << std::hex << dis(gen);
}
return ss.str();
}
int main(int argc, char** argv) {
OllamaConfig cfg;
@@ -79,6 +112,7 @@ int main(int argc, char** argv) {
};
char const* file_to_open = nullptr;
std::string auto_temp_file; // Path to auto-generated temp file (if any)
char const* prompt = nullptr;
bool start_new = false;
bool list_models = false;
@@ -168,11 +202,11 @@ int main(int argc, char** argv) {
{
std::cout << "Usage: drharness [options]\n"
<< "Options:\n"
<< " -F <file> Chat file (required)\n"
<< " -F <file> Chat file\n"
<< " -p <file> Pretty print a saved conversation JSON file\n"
<< " -t <tool> Tool name (can be specified multiple times)\n"
<< " -s <name> Skill name to enable (can be specified multiple times)\n"
<< " -n Start a new conversation\n"
<< " -n Start a new conversation (auto-generates temp file if -F not specified)\n"
<< " -m <prompt> Prompt message (required)\n"
<< " -M <model> Ollama model name\n"
<< " -f Open editor with full history (requires -F)\n"
@@ -280,6 +314,25 @@ int main(int argc, char** argv) {
else
agent_tools = master_registery.create_subregistry(tools);
// Auto-generate temp file if -n is specified without -F
if (start_new && !file_to_open) {
std::filesystem::path temp_dir = std::filesystem::temp_directory_path();
std::string uuid = generate_uuid();
auto temp_file_path = temp_dir / ("harness-" + uuid + ".json");
// Create empty temp file
std::ofstream temp_file(temp_file_path);
temp_file.close();
if (!std::filesystem::exists(temp_file_path)) {
std::cerr << "Error: Failed to create temp file" << std::endl;
exit(1);
}
file_to_open = temp_file_path.string().c_str();
auto_temp_file = temp_file_path.string();
}
if (!file_to_open)
{
std::cerr << "Chat file is required (-F)" << std::endl;
@@ -333,4 +386,9 @@ int main(int argc, char** argv) {
std::ofstream harness_state(file_to_open);
std::cout << reply << std::endl;
harness_state << nlohmann::json(harness.serialize());
// Print the auto-generated temp file path to stderr if it was auto-created
if (!auto_temp_file.empty()) {
std::cerr << auto_temp_file << std::endl;
}
}
+1
View File
@@ -37,3 +37,4 @@ add_dr_test(test_editor)
add_dr_test(test_tool_skill)
add_dr_test(test_skill_filter)
add_dr_test(test_skill_override)
add_dr_test(test_auto_temp_file)
+62
View File
@@ -0,0 +1,62 @@
#!/bin/bash
# test_auto_temp_file.sh - Validates auto-generation of temp files with -n flag
# Test 1: -n alone creates a temp file and prints path to stderr
OUTPUT=$("${DRHARNESS}" -n -m "test" -d <<< "$(be_done 'Test response from mock')" 2> stderr_output)
# Check that we got the expected response
if [ "${OUTPUT}" != "Test response from mock" ]; then
echo "FAIL: Expected 'Test response from mock', got '${OUTPUT}'"
exit 1
fi
# Check that stderr contains a path matching harness-*.json pattern
if ! grep -qE 'harness-[0-9a-f-]+\.json' stderr_output; then
echo "FAIL: Expected temp file path in stderr, got: $(cat stderr_output)"
exit 1
fi
# Extract the temp file path from stderr (last line)
TEMP_FILE=$(grep -E 'harness-[0-9a-f-]+\.json' stderr_output | tail -1)
# Verify the temp file exists
if [ ! -f "${TEMP_FILE}" ]; then
echo "FAIL: Temp file '${TEMP_FILE}' does not exist"
exit 1
fi
# Verify the temp file has content (the harness state was written to it)
FILE_SIZE=$(wc -c < "${TEMP_FILE}")
if [ "${FILE_SIZE}" -eq 0 ]; then
echo "FAIL: Temp file is empty, expected harness state to be written"
exit 1
fi
echo "PASS: auto_temp_file - temp file created and path printed to stderr"
# Test 2: -F <file> -n still works as before (preserves existing behavior)
touch "${TEST_TEMP_DIR}/existing.json"
EXISTING_OUTPUT=$("${DRHARNESS}" -F existing.json -n -m "test" -d <<< "$(be_done 'Existing file test')" 2> existing_stderr_output)
if [ "${EXISTING_OUTPUT}" != "Existing file test" ]; then
echo "FAIL: Expected 'Existing file test', got '${EXISTING_OUTPUT}'"
exit 1
fi
# The existing file should not have been modified if it was empty initially
# (except for the harness state being written to it)
# Test 3: Verify two -n calls create different files
FIRST_OUTPUT=$("${DRHARNESS}" -n -m "test" -d <<< "$(be_done 'First')" 2> first_stderr)
SECOND_OUTPUT=$("${DRHARNESS}" -n -m "test" -d <<< "$(be_done 'Second')" 2> second_stderr)
FIRST_FILE=$(grep -E 'harness-[0-9a-f-]+\.json' first_stderr | tail -1)
SECOND_FILE=$(grep -E 'harness-[0-9a-f-]+\.json' second_stderr | tail -1)
if [ "${FIRST_FILE}" = "${SECOND_FILE}" ]; then
echo "FAIL: Two -n calls created the same file: ${FIRST_FILE}"
exit 1
fi
echo "PASS: auto_temp_file - UUID uniqueness verified"
echo "PASS: auto_temp_file -F behavior preserved"