This isn't a problem that can ever be solved by direct control mode because it's also a problem for PvE. The AI is terrible at handling relatively fast craft because it only uses the speed to pick a range not to break away to recover shields or to circle.
These are not necessarily "fighters" in terms of size. Some of them are quite large. With huge and boost thrusters and engine rooms the design paradigm can exist all the way up to the limit of the build box or price cap for PvE opponents. Indeed, the need for a continuous thrusting flyby AI is more pressing when you're using larger engines as they suffer more ramp time. A fast broadsider or anything fast with low combat endurance that can regenerate (ie anything using shields or that doesn't generate enough ammo or batteries for sustained fire after its storages run dry) does better in my PvE experience doing fast flybys going straight in to the range of any narrow arc bow weapons and then veering off to pass as close as it can get to the target without colliding without ever cutting its long ramp time forward engines. Ships in this mode should not consider any braking engines for use in turning, turning only by feathering low ramp time off center forward engines and strafing engines. Ships in this mode should activate forward boost thrusters at their closet approach to minimize exposure of their tail. This behavior doesn't make sense for PvP because of the ring of death, but is very useful in PvE and would be equally useful to the AI against the player in PvE to make fast ships harder to deal with and to just provide variety in necessary strategies.
In the short run a flyby AI option is good for a lot of ships that just aren't doable right now for AI control but in the long run a more complicated AI system with triggers to switch between modes would be ideal.
The Starhawk is a decent example of a stock ship that would make use of multiple AI modes. It rushes in close and broadsides getting almost nothing from its railgun and uses its boost thrusters haphazardly. It should close to rail gun range and try to stay at railgun range with its tractor set to the railgun range or push if the railgun range exceeds tractor range (for the Starhawk it does, but for a similar rail and broadside design with two shorter rails it might not) for a period of time sufficient to cripple a "level appropriate" opponent with poor defenses then switch its tractor to 190m and close to cannon range and rotate into broadside to either clean up or fight something too defensive for its railgun to be useful. If the shields facing the enemy dropped below a designer set threshold it should rotate across its bow (never across its stern because the stern is weak, though a similar ship with a better defended stern might either not have a preference or even prefer to point the stern at the target on the assumption that the bow might have taken damage when closing) to present its other broadside. This threshold is dependent on how fast it can turn, how exposed the shield generators are, how layered the shields are, what level of Player ship it's expected to be a challenge for, how fragile its weapons are (with cannons it can afford to take some hits past shields before running, but if it had ion beams especially with crystals it would need to run well before the shields dropped).
A similar ship with shields or armor loops in the rear instead of PD it would also want to retreat, activate its boost thrusters, and switch its tractor beam into push mode if its shields on the side facing the target dropped below the designer designated indicated threshold which might ideally be different from the threshold for switching out of broadside mode. If the range started dropping while in retreat mode (or if it had aft shields if the aft shields went below a it should switch back into broadsider mode presenting the broadside with the most shield health.
This might take the form of a text field for XML (we know text can be stored in ship files because of the description field). For the StarHawk with aft shields instead of aft PD you might do something like this:
<defaultAI AImode="bow on"
range=550
tractorRange="push">
<switchmode AImode="broadside"
range=170
facings="orthogonal"
tractorRange=170>
<trigger rangeLT=200/>
<switchmode AImode="retreat">
<trigger shieldLT=0.5/>
<canceltrigger shieldLT=0.35/>
<canceltrigger
shieldAllGT=0.95>
<ammoGT threshold=0.95 ammotype="bullet"/>
</canceltrigger>
<canceltrigger rangeGT=550/>
</switchmode>
<switchfacing rotatethrough="bow">
<trigger shieldLT=0.35/>
</switchfacing>
</switchmode>
</defaultAI>
In this mockup shieldLT refers to the shields facing the target in the current mode. I'd say a shield covers its direct facing and the adjacent diagonal facings. There are geometries that use shields at 90 degrees, but it would be the directly facing shields covering the bow that are most vulnerable. Modded shields with wider arcs would be considered in wider arcs as guns are considered in more or fewer facings depending on their firing arc by the current AI. ShieldAllGT refers to all shields and there would be a ShieldAllLT to handle mods with linked shields. AmmoGT refers to all rooms that can contain the specified ammo type. The facings element of broadside is to allow ships like the DeathBox to favor the forward quarters while something like the StarHawk favors the 90 degree broadsides and probably isn't necessary in a first implementation. A trigger would be satisfied if all of its parameters are satisfied (if you want logical 'or' use two triggers).
My instinct would be to refactor AI into a class that contains a list or array of AIs that have a checkSwitch method returning an AI pointer using a data structure populated from their trigger and canceltrigger subelements. Cannceltrigger would go out to the defaultAI because if it went to the parent each AI object would need a pointer to the parent which would require special handling to avoid crashes when someone tried to cancel a defaultAI, but if it goes out to defaultAI that's a variable of the ship object. The individual AIs would be subclasses instantiated with parameters.
XML parsing errors should be silent outside sandbox mode and ships just default to a default AI with default parameters and no mode switches.