Skip to content

restart

restart

The make-it-running ladder for task containers.

Two entry points share one ladder: task_restart (stop if running, then start) and ensure_task_running (report if running, otherwise start). The start itself resumes the existing container when possible and recreates it in place through the launch-only mode runners when not.

__all__ = ['ensure_task_running', 'task_restart'] module-attribute

task_restart(project_name, task_id, *, fresh=False)

Bring a task's container back to running: stop if running, then start.

The start is a best-effort ladder. First rung: resume the existing container in place — kept as-is even when the project image was rebuilt underneath it, so a long-running task keeps its in-container state. A stale image is only warned about, not acted on (see _warn_if_stale_image). When the resume rung is gone — the container no longer exists or podman refuses to start it — recreate the container through the normal launch path: same task and container name, workspace reused as-is (never re-seeded), project config re-read, the task's persistent gate token reused (the workspace's origin URL embeds it, so it must survive the recreate), per-task settings carried over from the saved metadata.

fresh skips straight to the recreate rung — the explicit "recreate + restart" that picks up a rebuilt image, upgrading a task that a plain restart deliberately left on its old image.

Headless tasks (mode run) only ever take the resume rung: recreating one would replay its original prompt against the workspace.

Source code in src/terok/lib/orchestration/task_runners/restart.py
def task_restart(project_name: str, task_id: str, *, fresh: bool = False) -> None:
    """Bring a task's container back to running: stop if running, then start.

    The start is a best-effort ladder.  First rung: resume the existing
    container in place — kept as-is even when the project image was
    rebuilt underneath it, so a long-running task keeps its in-container
    state.  A stale image is only *warned* about, not acted on (see
    ``_warn_if_stale_image``).
    When the resume rung is gone — the container no longer exists or
    podman refuses to start it — recreate the container through the
    normal launch path: same task and container name, workspace reused
    as-is (never re-seeded), project config re-read, the task's
    persistent gate token reused (the workspace's origin URL embeds it,
    so it must survive the recreate), per-task settings carried over
    from the saved metadata.

    *fresh* skips straight to the recreate rung — the explicit
    "recreate + restart" that picks up a rebuilt image, upgrading a task
    that a plain restart deliberately left on its old image.

    Headless tasks (mode ``run``) only ever take the resume rung:
    recreating one would replay its original prompt against the
    workspace.
    """
    _make_running(project_name, task_id, bounce=True, fresh=fresh)

ensure_task_running(project_name, task_id, *, mode=None, unrestricted=None)

Bring a task to running without bouncing it.

The attach flavor of the restart ladder: already running → report how to reach it; stopped → resume; container gone → launch through the mode runner. mode overrides the task's recorded mode — an attach picks the interface, and a first attach on a fresh task records it. unrestricted seeds a launch; a resume keeps the existing container as-is.

Source code in src/terok/lib/orchestration/task_runners/restart.py
def ensure_task_running(
    project_name: str,
    task_id: str,
    *,
    mode: str | None = None,
    unrestricted: bool | None = None,
) -> None:
    """Bring a task to running without bouncing it.

    The attach flavor of the restart ladder: already running → report
    how to reach it; stopped → resume; container gone → launch through
    the mode runner.  *mode* overrides the task's recorded mode — an
    attach picks the interface, and a first attach on a fresh task
    records it.  *unrestricted* seeds a launch; a resume keeps the
    existing container as-is.
    """
    _make_running(
        project_name,
        task_id,
        bounce=False,
        fresh=False,
        mode_override=mode,
        unrestricted=unrestricted,
    )