{# Status -> dot colour (visual scan). Amber = needs attention, green = ok, dim = not installed / unknown. #} {% set dot = { 'up-to-date': '#3fb950', 'upgrade-available': '#d29922', 'running-stale': '#db6d28', 'not-installed': '#484f58', 'unknown': '#6e7681' } %} {% for e in snapshot.engines %} {% set absent = e.status == 'not-installed' %} {% endfor %}
Engine Running Installed Available Status Changelog
{{ e.display or e.engine_name }} {% if e.source == 'aisrv' %} (aisrv){% endif %} {{ e.running or '—' }} {{ e.installed or '—' }} {{ e.available or '—' }} {% if e.status == 'up-to-date' %} up-to-date {% elif e.status == 'upgrade-available' %} upgrade available {% elif e.status == 'running-stale' %} running stale {% elif e.status == 'not-installed' %} not installed {% else %} unknown {% endif %} {% if e.changelog_url %} {% else %}—{% endif %}
{# Actionable engines: upgrade-available or running-stale. We deliberately render copy-pastable CLI snippets rather than live POST buttons — the same decision as the fleet grid. A live button would mean the operator's Bearer token lives in localStorage, where a stored XSS in any version/notes field could steal it and ride the authenticated upgrade endpoint. The token never leaves the operator's shell this way. #} {% set actionable = snapshot.engines | selectattr("status", "in", ["upgrade-available", "running-stale"]) | list %} {% if actionable %}
Upgrade commands (copy-paste)
{% for e in actionable %}{% if e.status == 'running-stale' %}aisctl restart {{ e.engine_name }}   # running process predates the installed binary
{% else %}aisctl upgrade {{ e.engine_name }} --restart   # brew upgrade + restart (formula-whitelisted)
{% endif %}{% endfor %}

Requires asiai-inference-server (aisctl). Only brew-whitelisted engines can be upgraded this way; others are pip/manual.

{% endif %}