AlgoTune Agent
Command-driven algorithm optimizer with evaluation tools, profiling, multi-file edits, and best-snapshot restore.
"""Encode AlgoTune Agent's multi-file workspace as one Galapagos candidate artifact.
Galapagos evaluates one candidate file. AlgoTune agents can create helper modules, build metadata,
and Cython/Pythran/DaCe sources. A small import-time bootstrap materializes those sidecars before
the editable ``solver.py`` body executes, preserving the upstream workspace model without changing
the task evaluator contract.
"""
from __future__ import annotations
import ast
import base64
import hashlib
import json
import re
import warnings
from pathlib import PurePosixPath
from .validator import tampering_error
_MANIFEST_PREFIX = "# ALGOTUNE-WORKSPACE-V1:"
_SOLVER_MARKER = "# ALGOTUNE-SOLVER-PY-V1"
_SAFE_FILE = re.compile(r"^[A-Za-z0-9_./-]+$")
def validate_filename(name: str) -> str:
name = str(name).strip().replace("\\", "/")
path = PurePosixPath(name)
if (
not name
or not _SAFE_FILE.fullmatch(name)
or path.is_absolute()
or ".." in path.parts
or any(part.startswith(".algotune_") for part in path.parts)
or name.endswith("/")
):
raise ValueError(
f"Invalid filename {name!r}; use a relative path containing letters, numbers, "
"dots, dashes, underscores, or slashes"
)
return path.as_posix()
def unpack_workspace(candidate: str) -> dict[str, str]:
"""Return virtual files; an ordinary candidate is simply ``solver.py``."""
lines = candidate.splitlines()
if not lines or not lines[0].startswith(_MANIFEST_PREFIX):
return {"solver.py": candidate}
if len(lines) < 2 or not lines[1].startswith("import base64 as _at_b64"):
# A solver is allowed to contain arbitrary comments, including one that resembles our
# manifest sentinel. Only generated candidates carry the bootstrap signature too.
return {"solver.py": candidate}
try:
encoded = lines[0][len(_MANIFEST_PREFIX) :].strip()
payload = json.loads(base64.urlsafe_b64decode(encoded.encode()).decode())
if not isinstance(payload, dict):
raise ValueError("workspace manifest is not an object")
files = {validate_filename(k): str(v) for k, v in payload.items()}
# Current bundles keep solver.py in the manifest and compile it as an independent module
# source. This preserves module docstrings and ``from __future__`` placement even though a
# bootstrap has to run first. Keep reading the earlier development format so checkpoints
# written while the port was being tested remain resumable.
if "solver.py" in files and _SOLVER_MARKER not in lines:
return files
marker = lines.index(_SOLVER_MARKER)
solver = "\n".join(lines[marker + 1 :])
if candidate.endswith("\n"):
solver += "\n"
files["solver.py"] = solver
return files
except Exception as exc: # noqa: BLE001 - malformed model-authored artifact
raise ValueError(f"Malformed AlgoTune workspace bundle: {exc}") from exc
def _bootstrap(files: dict[str, str]) -> str:
payload = base64.urlsafe_b64encode(
json.dumps(files, sort_keys=True, separators=(",", ":")).encode()
).decode()
digest = hashlib.sha256(payload.encode()).hexdigest()[:16]
# This code executes inside the task sandbox, before its stopwatch starts. That is the same
# place upstream AlgoTune pays setup/Cython compilation cost.
return f'''{_MANIFEST_PREFIX} {payload}
import base64 as _at_b64, json as _at_json, os as _at_os
import pathlib as _at_path, shutil as _at_shutil, subprocess as _at_subprocess, sys as _at_sys
import zipfile as _at_zipfile
_at_files = _at_json.loads(_at_b64.urlsafe_b64decode({payload!r}).decode())
_at_root = _at_path.Path("/tmp/algotune_workspace_{digest}")
_at_root.mkdir(parents=True, exist_ok=True)
for _at_name, _at_text in _at_files.items():
_at_target = _at_root / _at_name
_at_target.parent.mkdir(parents=True, exist_ok=True)
if not _at_target.exists() or _at_target.read_text() != _at_text:
_at_target.write_text(_at_text)
_at_pythran = [
_at_name for _at_name, _at_text in _at_files.items()
if _at_name.endswith(".py") and "pythran export" in _at_text.lower()
]
_at_dace = [
_at_name for _at_name, _at_text in _at_files.items()
if _at_name.endswith(".py") and "@dace.program" in _at_text
]
_at_build = "setup.py" if "setup.py" in _at_files else (
"pyproject.toml" if "pyproject.toml" in _at_files else ""
)
if (_at_build or _at_pythran or _at_dace) and not (_at_root / ".algotune_build_ok").exists():
if "setup.py" in _at_files:
try:
_at_proc = _at_subprocess.run(
[_at_sys.executable, "setup.py", "build_ext", "--inplace"], cwd=_at_root,
capture_output=True, text=True, timeout=1800,
)
except _at_subprocess.TimeoutExpired as _at_exc:
raise RuntimeError("Cython compilation failed: timed out after 1800 seconds") from _at_exc
if _at_proc.returncode:
raise RuntimeError("Cython compilation failed: " + (_at_proc.stderr or _at_proc.stdout)[-2000:])
elif "pyproject.toml" in _at_files:
_at_wheel_dir = _at_root / ".algotune_wheels"
_at_wheel_dir.mkdir(exist_ok=True)
try:
_at_proc = _at_subprocess.run(
[_at_sys.executable, "-m", "pip", "wheel", ".", "--no-deps",
"--no-build-isolation", "--wheel-dir", str(_at_wheel_dir)],
cwd=_at_root, capture_output=True, text=True, timeout=1800,
)
except _at_subprocess.TimeoutExpired as _at_exc:
raise RuntimeError("Cython compilation failed: timed out after 1800 seconds") from _at_exc
if _at_proc.returncode:
raise RuntimeError("Cython compilation failed: " + (_at_proc.stderr or _at_proc.stdout)[-2000:])
for _at_wheel in _at_wheel_dir.glob("*.whl"):
with _at_zipfile.ZipFile(_at_wheel) as _at_archive:
_at_archive.extractall(_at_root)
if _at_build:
_at_extensions = [
_at_extension
for _at_extension in list(_at_root.glob("**/*.so")) + list(_at_root.glob("**/*.pyd"))
if "build" not in _at_extension.relative_to(_at_root).parts
]
if not _at_extensions:
_at_extensions = list((_at_root / "build").glob("**/*.so")) + list(
(_at_root / "build").glob("**/*.pyd")
)
for _at_extension in _at_extensions:
_at_shutil.copy2(_at_extension, _at_root / _at_extension.name)
if not _at_extensions:
raise RuntimeError("Cython compilation failed: build produced no .so/.pyd extension")
for _at_name in _at_pythran:
_at_compile_target = _at_root / _at_name
try:
_at_proc = _at_subprocess.run(
[_at_sys.executable, "-m", "pythran", "-O3", "-march=native",
_at_compile_target.name], cwd=_at_compile_target.parent,
capture_output=True, text=True, timeout=300,
)
except _at_subprocess.TimeoutExpired as _at_exc:
raise RuntimeError("Pythran compilation failed: timed out after 300 seconds") from _at_exc
if _at_proc.returncode:
raise RuntimeError("Pythran compilation failed: " + (_at_proc.stderr or _at_proc.stdout)[-2000:])
for _at_name in _at_dace:
_at_dace_target = _at_root / _at_name
try:
_at_proc = _at_subprocess.run(
[_at_sys.executable, "-c", "import " + _at_dace_target.stem],
cwd=_at_dace_target.parent, capture_output=True, text=True, timeout=300,
)
except _at_subprocess.TimeoutExpired as _at_exc:
raise RuntimeError("DaCe compilation failed: timed out after 300 seconds") from _at_exc
if _at_proc.returncode:
raise RuntimeError("DaCe compilation failed: " + (_at_proc.stderr or _at_proc.stdout)[-2000:])
(_at_root / ".algotune_build_ok").write_text("ok")
if str(_at_root) not in _at_sys.path:
_at_sys.path.insert(0, str(_at_root))
_at_solver_path = _at_root / "solver.py"
_at_solver_source = _at_solver_path.read_text()
del _at_b64, _at_json, _at_os, _at_path, _at_shutil, _at_subprocess, _at_sys, _at_zipfile
del _at_files
del _at_name, _at_text, _at_target, _at_pythran, _at_dace, _at_build
exec(compile(_at_solver_source, str(_at_solver_path), "exec"), globals(), globals())
'''
def pack_workspace(files: dict[str, str]) -> str:
normalized = {validate_filename(name): str(content) for name, content in files.items()}
solver = normalized.get("solver.py", "")
if (
not any(name != "solver.py" for name in normalized)
and not solver.startswith(_MANIFEST_PREFIX)
):
return solver
normalized["solver.py"] = solver
return _bootstrap(normalized)
def syntax_error(files: dict[str, str]) -> str | None:
"""Apply the upstream edit-time critical Python linter gate."""
for name, source in files.items():
if not name.endswith(".py"):
continue
try:
with warnings.catch_warnings():
warnings.simplefilter("ignore", SyntaxWarning)
tree = ast.parse(source, filename=name)
except SyntaxError as exc:
return f"{name}:{exc.lineno}:{exc.offset}: {exc.msg}"
violation = tampering_error(tree, source)
if violation:
return f"{name}: {violation}"
return None
def numbered(source: str, start_line: int = 1, limit: int = 100) -> str:
lines = source.splitlines()
start = max(1, int(start_line))
selected = lines[start - 1 : start - 1 + limit]
return "\n".join(f"{index:4d}: {line}" for index, line in enumerate(selected, start))
def replace_lines(source: str, start: int, end: int, content: str) -> str:
lines = source.splitlines(keepends=True)
cleaned = content.lstrip(":") if content else ""
replacement = [line + "\n" for line in cleaned.splitlines()]
if start < 0 or end < 0 or (start > 0 and end < start):
raise ValueError(f"invalid line range {start}-{end}")
if start == 0:
result = replacement + lines[end:]
else:
if start > len(lines) + 1:
raise ValueError(
f"start line {start} is greater than the file length ({len(lines)}) + 1"
)
result = lines[: start - 1] + replacement + lines[end:]
return "".join(result)
def delete_lines(source: str, start: int, end: int) -> str:
if start < 1 or end < start:
raise ValueError(f"invalid delete range {start}-{end}")
return replace_lines(source, start, end, "")