AlgoTune Agent
Command-driven algorithm optimizer with evaluation tools, profiling, multi-file edits, and best-snapshot restore.
"""AlgoTune Agent's one-command loop as a Galapagos Proposer."""
from __future__ import annotations
import json
import os
import re
import subprocess
import sys
import tempfile
import time
import uuid
from dataclasses import dataclass
from ...components import Proposer
from ...components.proposer import (
_emit_tool_events,
_model_call_record,
_tooling_summary,
)
from ...components.evaluator import ContainerEvaluator, _PROVIDER_SECRETS
from ...models import Prompt
from ...records import EvalResult, Genome
from .population import algotune_priority
from .validator import protected_filename_error
from .workspace import (
delete_lines,
numbered,
pack_workspace,
replace_lines,
syntax_error,
unpack_workspace,
validate_filename,
)
_COMMANDS = {
"edit", "ls", "view_file", "revert", "reference", "eval_input", "eval",
"delete", "profile", "profile_lines",
}
_FENCE = re.compile(r"(?ms)^```([^\n`]*)[ \t]*\n(.*?)^```[ \t]*$")
_THINK = re.compile(r"(?is)<(?:think|thinking)>.*?</(?:think|thinking)>")
class CommandParseError(ValueError):
pass
@dataclass(frozen=True)
class ParsedCommand:
name: str
args: dict
raw: str
def _command_text(response: str) -> str:
clean = _THINK.sub("", response or "").strip()
blocks = list(_FENCE.finditer(clean))
if len(blocks) > 1:
raise CommandParseError("Multiple command blocks found; send one and only one command")
if blocks:
match = blocks[0]
if clean[match.end() :].strip():
raise CommandParseError("Text found after the command block")
language, body = match.group(1).strip(), match.group(2).strip("\n")
first = body.strip().split(maxsplit=1)[0] if body.strip() else ""
if language in _COMMANDS:
return f"{language}\n{body}".strip()
if first in _COMMANDS:
return body.strip()
raise CommandParseError("The fenced block does not contain an AlgoTune command")
first = clean.split(maxsplit=1)[0] if clean else ""
if first in _COMMANDS:
return clean
raise CommandParseError("No command block found")
def parse_command(response: str) -> ParsedCommand:
text = _command_text(response)
name = text.split(maxsplit=1)[0]
if name == "edit":
match = re.fullmatch(
r"edit\s*\nfile:\s*(\S+)\s*\nlines:\s*(\d+)\s*-\s*(\d+)\s*"
r"\n---[ \t]*\n(.*?)\n---\s*",
text,
re.DOTALL,
)
if not match:
raise CommandParseError("Invalid edit format")
return ParsedCommand(name, {
"file": match.group(1), "start": int(match.group(2)),
"end": int(match.group(3)), "content": match.group(4),
}, text)
if name == "delete":
match = re.fullmatch(
r"delete\s*\nfile:\s*(\S+)\s*\nlines:\s*(\d+)\s*-\s*(\d+)\s*", text
)
if not match:
raise CommandParseError("Invalid delete format")
return ParsedCommand(name, {
"file": match.group(1), "start": int(match.group(2)), "end": int(match.group(3)),
}, text)
if name == "view_file":
match = re.fullmatch(r"view_file\s+(\S+)(?:\s+(\d+))?\s*", text)
if not match:
raise CommandParseError("Invalid view_file format")
return ParsedCommand(name, {"file": match.group(1), "start": int(match.group(2) or 1)}, text)
if name in {"ls", "revert", "eval"}:
if not re.fullmatch(name + r"\s*", text):
raise CommandParseError(f"Invalid {name} format")
return ParsedCommand(name, {}, text)
if name in {"reference", "eval_input"}:
match = re.fullmatch(name + r"\s+([\s\S]+)", text)
if not match:
raise CommandParseError(f"Invalid {name} format")
return ParsedCommand(name, {"input": match.group(1).strip()}, text)
if name == "profile":
match = re.fullmatch(r"profile\s+(\S+\.py)\s+([\s\S]+)", text)
if not match:
raise CommandParseError("Invalid profile format")
return ParsedCommand(name, {"file": match.group(1), "input": match.group(2).strip()}, text)
if name == "profile_lines":
match = re.fullmatch(
r"profile_lines\s+(\S+\.py)\s+((?:\d+(?:-\d+)?)(?:\s*,\s*\d+(?:-\d+)?)*)\s+([\s\S]+)",
text,
)
if not match:
raise CommandParseError("Invalid profile_lines format")
return ParsedCommand(name, {
"file": match.group(1), "lines": match.group(2), "input": match.group(3).strip(),
}, text)
raise CommandParseError(f"Unknown command {name!r}")
def _call_record(generation) -> dict:
return _model_call_record(generation)
def format_evaluation(result: EvalResult) -> str:
def render(value):
return f"{value:.6g}" if isinstance(value, (int, float)) else str(value)
metrics = ", ".join(f"{key}={render(value)}" for key, value in result.metrics.items()) or "none"
feedback = result.text_feedback or (result.artifacts or {}).get("text_feedback") or ""
return f"Evaluation complete. valid={bool(result.valid)}; metrics: {metrics}.\n{feedback}".strip()
_TOOL_RUNNER = r'''
import ast, contextlib, copy, cProfile, importlib.util, io, json, pathlib, pstats, re, sys, traceback
ev_path, candidate_path, mode, raw_input, focus, requested_file = sys.argv[1:7]
def load(name, path):
spec = importlib.util.spec_from_file_location(name, path)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
def parse_input(text):
try:
return ast.literal_eval(text)
except Exception:
return json.loads(text)
def plain(value):
if hasattr(value, "tolist"):
return plain(value.tolist())
if isinstance(value, dict):
return {str(key): plain(item) for key, item in value.items()}
if isinstance(value, (list, tuple)):
return [plain(item) for item in value]
return value
def selected_lines(spec):
chosen = set()
for part in spec.split(","):
if not part.strip():
continue
bounds = [int(item) for item in part.strip().split("-", 1)]
chosen.update(range(bounds[0], bounds[-1] + 1))
return chosen
def profile_target(candidate):
if not requested_file or requested_file == "solver.py":
target = candidate
else:
entrypoint = getattr(candidate, "run_solver", None)
source = pathlib.Path(getattr(entrypoint, "__code__", None).co_filename)
target_path = source.parent / requested_file
if not target_path.is_file():
raise FileNotFoundError("File not found: " + requested_file)
target = load("_algotune_profile_target", str(target_path))
function = getattr(target, "run_solver", None)
if callable(function):
return target, function
solver_class = getattr(target, "Solver", None)
if solver_class is not None:
function = getattr(solver_class(), "solve", None)
if not callable(function):
raise AttributeError(
"profile target missing run_solver(problem) or class Solver.solve(problem): "
+ (requested_file or "solver.py")
)
return target, function
try:
evaluator = load("_algotune_tool_evaluator", ev_path)
problem = parse_input(raw_input)
if mode == "reference":
out = evaluator.reference_solve(problem)
result = {"reference": plain(out)}
else:
candidate = load("_algotune_tool_candidate", candidate_path)
if not callable(getattr(candidate, "run_solver", None)):
raise AttributeError("program missing run_solver(problem)")
if mode == "eval_input":
ref = evaluator.reference_solve(copy.deepcopy(problem))
stream = io.StringIO()
with contextlib.redirect_stdout(stream):
out = candidate.run_solver(copy.deepcopy(problem))
result = {"solver": plain(out), "reference": plain(ref), "stdout": stream.getvalue(),
"correct": bool(evaluator.is_correct(copy.deepcopy(problem), out))}
else:
stream = io.StringIO()
target, target_function = profile_target(candidate)
try:
from line_profiler import LineProfiler
profiler = LineProfiler()
profiler.add_function(target_function)
for value in vars(target).values():
if isinstance(value, type):
solve = getattr(value, "solve", None)
if callable(solve):
try:
profiler.add_function(solve)
except Exception:
pass
profiler.runcall(target_function, problem)
profiler.print_stats(stream=stream)
report = stream.getvalue()
except Exception:
profiler = cProfile.Profile()
profiler.runcall(target_function, problem)
pstats.Stats(profiler, stream=stream).sort_stats("cumulative").print_stats(25)
report = stream.getvalue()
if mode == "profile_lines" and focus:
wanted = selected_lines(focus)
try:
source_lines = open(candidate_path, encoding="utf-8").read().splitlines()
marker = source_lines.index("# ALGOTUNE-SOLVER-PY-V1") + 1
except (OSError, ValueError):
marker = 0
actual = wanted | {line + marker for line in wanted}
kept = []
for line in report.splitlines():
match = re.match(r"^\s*(\d+)\s+", line)
if match is None or int(match.group(1)) in actual:
kept.append(line)
report = "\n".join(kept)
result = {"profile": report, "focus_lines": focus or None}
sys.stdout.write("<<<ALGOTUNE_TOOL>>>" + json.dumps(result, default=str))
except Exception as exc:
sys.stdout.write("<<<ALGOTUNE_TOOL>>>" + json.dumps(
{"error": str(exc), "traceback": traceback.format_exc()}
))
'''
class AlgoTuneProposer(Proposer):
"""One LLM message, one parsed command, one workspace transition."""
def _chat(self, prompt: Prompt, env):
memory = env.memory
memory.initialize(prompt.system, prompt.user)
token_limit = (
getattr(env.model, "context_length", None)
or getattr(env.model, "context_window", None)
or getattr(env.model, "max_tokens", None)
or 4000
)
messages = memory.messages(token_limit=int(token_limit))
started = time.monotonic()
interface = "chat"
try:
try:
generation = env.model.chat(messages)
except (AttributeError, NotImplementedError):
interface = "generate"
flattened = "\n\n".join(
f"[{message['role'].upper()}]\n{message['content']}" for message in messages
)
generation = env.model.generate(Prompt(system="", user=flattened))
except Exception as exc:
if env.ctx is not None:
env.ctx.emit_event(
event_type="model_call",
action="generate",
status="failed",
component_role="proposer",
component_name=type(self).__name__,
attempt_number=env.attempt_number,
evolution_track="solution",
caused_by_event_ids=([getattr(env.selection, "_etif_event_id", None)]
if getattr(env.selection, "_etif_event_id", None) else []),
duration_seconds=time.monotonic() - started,
error=exc,
details={
"purpose": "candidate_proposal",
"call_id": None,
"model": str(getattr(env.model, "name", type(env.model).__name__)),
"prompt": {"system": None, "user": None, "messages": messages},
"response": {"text": None, "reasoning": None},
"usage": {
"prompt_tokens": None,
"cached_prompt_tokens": None,
"completion_tokens": None,
"cost_usd": None,
},
"parameters": {"interface": interface},
},
)
raise
if not generation.latency_s:
generation.latency_s = time.monotonic() - started
if not generation.model:
generation.model = str(getattr(env.model, "name", type(env.model).__name__))
if env.ctx is not None:
env.ctx.record_cost(
generation.cost_usd, generation.prompt_tokens, generation.completion_tokens
)
call_record = _call_record(generation)
model_call_event = (env.ctx.emit_event(
event_type="model_call",
action="generate",
status="completed",
component_role="proposer",
component_name=type(self).__name__,
attempt_number=env.attempt_number,
evolution_track="solution",
caused_by_event_ids=([getattr(env.selection, "_etif_event_id", None)]
if getattr(env.selection, "_etif_event_id", None) else []),
duration_seconds=call_record.get("latency_s"),
details={
"purpose": "candidate_proposal",
"call_id": call_record.get("call_id"),
"model": call_record.get("model"),
"prompt": {"system": None, "user": None, "messages": messages},
"response": {"text": generation.text, "reasoning": generation.reasoning},
"usage": {
"prompt_tokens": call_record.get("prompt_tokens"),
"cached_prompt_tokens": call_record.get("cached_tokens"),
"completion_tokens": call_record.get("completion_tokens"),
"cost_usd": call_record.get("cost_usd"),
},
"parameters": {
"reasoning_effort": call_record.get("effort"),
"reasoning_summary": call_record.get("reasoning_summary"),
"interface": interface,
},
"accounting": {
"reasoning_tokens": call_record.get("reasoning_tokens"),
"reasoning_summary_present": call_record.get(
"reasoning_summary_present"
),
"cache_write_tokens": call_record.get("cache_write_tokens"),
"cost_source": call_record.get("cost_source"),
"pricing_source": call_record.get("pricing_source"),
},
"tooling": _tooling_summary(call_record),
},
) if env.ctx is not None else None)
_emit_tool_events(
env.ctx,
model_call_event_id=model_call_event,
call=call_record,
attempt_number=env.attempt_number,
evolution_track="solution",
)
return generation, messages, call_record, model_call_event
@staticmethod
def _best(pool: list[Genome]) -> Genome | None:
return max(pool, key=algotune_priority) if pool else None
@staticmethod
def _tool(command: ParsedCommand, parent: Genome, env, files: dict[str, str]) -> str:
if command.name == "eval":
started = time.monotonic()
try:
evaluated = env.evaluator.evaluate(parent)
except Exception as exc:
if env.ctx is not None:
env.ctx.blackboard["_algotune_diagnostic_evaluation"] = {
"duration_seconds": time.monotonic() - started,
"data_split": "task_default",
"error": {
"error_type": type(exc).__name__,
"message": str(exc),
},
}
return f"Diagnostic failed: {type(exc).__name__}: {exc}"
if env.ctx is not None:
env.ctx.blackboard["_algotune_diagnostic_evaluation"] = {
"duration_seconds": time.monotonic() - started,
"data_split": "task_default",
"result": {
"is_valid": bool(evaluated.valid),
"metrics": dict(evaluated.metrics or {}),
"text_feedback": evaluated.text_feedback,
},
}
return format_evaluation(evaluated)
filename = command.args.get("file")
if filename:
filename = validate_filename(filename)
if filename not in files:
return f"File not found: {filename}"
evaluator_path = getattr(env.evaluator, "evaluator_path", None)
if not evaluator_path:
return (
"This diagnostic requires a local task evaluator. Run this scaffold through "
"`galapagos run`; its whole-loop task-container mode provides that environment."
)
timeout = max(30, int(getattr(env.evaluator, "timeout", 120)))
tool_args = [
command.name, command.args["input"], command.args.get("lines", ""),
command.args.get("file", ""),
]
candidate_path = ""
container = None
try:
if isinstance(env.evaluator, ContainerEvaluator):
# Programmatic ``scaffold.run`` does not use the CLI's whole-loop orchestration.
# Attach diagnostics to its task evaluator container so they still see the exact task
# packages. The CLI path uses a local evaluator *inside* that image and takes the branch
# below instead.
env.evaluator._ensure_started()
container = env.evaluator._container
if container is None:
raise RuntimeError("task evaluator container did not start")
candidate_path = f"/tmp/algotune_tool_{uuid.uuid4().hex}.py"
container.put_bytes(
parent.content.encode(), candidate_path, user=env.evaluator.run_user
)
inside_evaluator = f"{env.evaluator._EVAL_DIR}/{env.evaluator.evaluator_name}"
process = container.exec(
["python3", "-c", _TOOL_RUNNER, inside_evaluator, candidate_path, *tool_args],
workdir=env.evaluator._EVAL_DIR,
timeout=timeout,
user=env.evaluator.run_user,
)
else:
fd, candidate_path = tempfile.mkstemp(suffix=".py")
with os.fdopen(fd, "w", encoding="utf-8") as handle:
handle.write(parent.content)
environment = dict(os.environ)
for key in _PROVIDER_SECRETS:
environment.pop(key, None)
process = subprocess.run(
[
sys.executable, "-c", _TOOL_RUNNER, str(evaluator_path), candidate_path,
*tool_args,
],
capture_output=True,
text=True,
timeout=timeout,
cwd=os.path.dirname(os.path.abspath(str(evaluator_path))),
env=environment,
)
if "<<<ALGOTUNE_TOOL>>>" not in process.stdout:
return "Diagnostic failed: " + (process.stderr or process.stdout or "no output")[-2000:]
payload = json.loads(process.stdout.split("<<<ALGOTUNE_TOOL>>>", 1)[1])
if payload.get("error"):
return f"Diagnostic failed: {payload['error']}\n{payload.get('traceback', '')}".strip()
return json.dumps(payload, indent=2, default=str)
except subprocess.TimeoutExpired:
return f"Diagnostic timed out after {timeout}s"
except Exception as exc: # noqa: BLE001 - a tool failure is feedback, not a run failure
return f"Diagnostic failed: {type(exc).__name__}: {exc}"
finally:
if container is not None and candidate_path:
try:
container.exec(["rm", "-f", candidate_path], user=env.evaluator.run_user)
except Exception: # noqa: BLE001 - diagnostic cleanup must not mask its result
pass
elif candidate_path:
try:
os.remove(candidate_path)
except OSError:
pass
def _execute(self, command: ParsedCommand, parent: Genome, env) -> tuple[str, bool, str, bool]:
files = unpack_workspace(parent.content)
name = command.name
if name == "ls":
listing = "\n".join(
filename
for filename in sorted(files)
if "/" not in filename
and not filename.startswith(".")
and filename != "__init__.py"
)
return parent.content, False, f"File list:\n{listing}", False
if name == "view_file":
filename = validate_filename(command.args["file"])
if filename not in files:
return parent.content, False, f"File not found: {filename}", False
view = numbered(files[filename], command.args["start"], 100)
return parent.content, False, view or "(empty file)", False
if name in {"reference", "eval_input", "profile", "profile_lines", "eval"}:
return parent.content, False, self._tool(command, parent, env, files), False
if name == "revert":
best = self._best(env.selection.pool)
if best is None:
return parent.content, False, "No saved state to revert to", False
detail = f"Restored best snapshot {best.id} (score={best.fitness:.6g})."
# Upstream copies the saved snapshot and reloads it; it does not run dataset evaluation.
# The existing measured Genome is already that snapshot, so after_step moves the mutable
# current pointer to it without minting a duplicate scored candidate.
return best.content, False, detail, False
filename = validate_filename(command.args["file"])
protected_error = protected_filename_error(filename)
if protected_error:
return parent.content, False, protected_error, False
old = files.get(filename, "")
try:
if name == "edit":
files[filename] = replace_lines(
old, command.args["start"], command.args["end"], command.args["content"]
)
else:
files[filename] = delete_lines(old, command.args["start"], command.args["end"])
except ValueError as exc:
return parent.content, False, str(exc), False
lint = syntax_error(files)
if lint:
return parent.content, False, f"Critical syntax error; edit was not applied: {lint}", False
candidate = pack_workspace(files)
changed = candidate != parent.content
detail = (
f"{name} applied to {filename}; trusted evaluation follows."
if changed else "Command made no change."
)
return candidate, changed, detail, changed
def propose(self, prompt: Prompt, env) -> Genome:
parent = env.selection.parent
if parent is None:
raise RuntimeError("AlgoTune requires a current workspace parent")
generation, messages, call_record, model_call_event = self._chat(prompt, env)
env.memory.add("assistant", generation.text)
if env.ctx is not None:
env.ctx.blackboard.pop("_algotune_diagnostic_evaluation", None)
command = None
try:
command = parse_command(generation.text)
content, changed, result, needs_evaluation = self._execute(command, parent, env)
except (CommandParseError, ValueError) as exc:
content, changed, result, needs_evaluation = parent.content, False, str(exc), False
child = parent.child(content, generation=parent.metadata.get("generation", 0) + 1)
child.metadata.update({
"changed": bool(changed),
"parent_metrics": dict(parent.scores),
"changes": command.raw[:500] if command else "invalid command",
"algotune_command": command.name if command else "parse_error",
"algotune_command_raw": command.raw if command else "",
"algotune_result": result,
"algotune_needs_evaluation": bool(needs_evaluation),
"algotune_edited_file": command.args.get("file") if command else None,
"algotune_revert_target_id": (
self._best(env.selection.pool).id
if command is not None and command.name == "revert" and env.selection.pool
else None
),
"model_call": call_record,
})
child.artifacts["response"] = generation.text
child.artifacts["reasoning"] = generation.reasoning
child.trace["algotune_chat_messages"] = messages
child.trace["proposal_model_call_event_id"] = model_call_event
child.trace["proposal_memory_writes"] = [{
"memory_name": "conversation_history",
"entry_type": "assistant_message",
"content": generation.text,
}]
child.trace["proposal_prompt"] = {
"system": "",
"user": "\n\n".join(
f"[{message['role'].upper()}]\n{message['content']}" for message in messages
),
}
diagnostic = (
env.ctx.blackboard.pop("_algotune_diagnostic_evaluation", None)
if env.ctx is not None else None
)
if diagnostic:
child.trace["diagnostic_evaluation"] = diagnostic
if not changed:
child.trace["etif_no_candidate"] = True
child.trace["no_candidate_reason"] = (
"command_parse_error" if command is None else
"control_action" if command.name in {
"ls", "view_file", "reference", "eval_input", "eval",
"profile", "profile_lines", "revert",
} else "no_change"
)
return child