	static string readMessageLine(Details &details) {
		TRACE_POINT();
		while (true) {
			string result = details.io.readLine(1024 * 4, &details.timeout);
			if (result.empty()) {
				return result;
			} else if (startsWith(result, "!> ")) {
				result.erase(0, sizeof("!> ") - 1);
				return result;
			} else {
				if (details.stderrCapturer != NULL) {
					details.stderrCapturer->appendToBuffer(result);
				}
				if (details.forwardStderr) {
					write(details.forwardStderrTo, result.data(), result.size());
				}
			}
		}
	}
	static string readMessageLine(Details &details) {
		TRACE_POINT();
		while (true) {
			string result = details.io.readLine(1024 * 4, &details.timeout);
			if (result.empty()) {
				return result;
			} else if (startsWith(result, "!> ")) {
				result.erase(0, sizeof("!> ") - 1);
				return result;
			} else {
				if (details.stderrCapturer != NULL) {
					details.stderrCapturer->appendToBuffer(result);
				}
				if (details.forwardStderr) {
					write(details.forwardStderrTo, result.data(), result.size());
				}
			}
		}
	}