{% for poll in snapshot.nodes %}

{{ poll.nickname }}

{% if poll.ok %} ok {% else %} DOWN {% endif %}
{{ poll.url }}
{% if poll.ok and poll.snapshot %} {# /api/v1/snapshot exposes engines under "engines_status" (see asiai.collectors.snapshot.collect_full_snapshot). #} {% set engines = poll.snapshot.engines_status or [] %} {% if engines is iterable and engines is not string %} {% if engines|length > 0 %} {% set reachable_engines = engines | selectattr("reachable") | list %} {% set total_models = [] %} {% for e in engines %} {% for m in (e.models or []) %} {% set _ = total_models.append(m) %} {% endfor %} {% endfor %}
{{ reachable_engines|length }}/{{ engines|length }} engines reachable
{% else %}
No engines reported.
{% endif %} {% endif %} {% elif not poll.ok %}
Error: {{ poll.error }}
{% endif %}
Latency: {{ '%.0f'|format(poll.latency_ms) }}ms
{# Phase 2 — command palette per card. We deliberately don't expose live POST buttons here: a stored XSS in any nickname/error field would otherwise let an attacker steal the operator's Bearer token from localStorage and ride the same /api/v1/fleet/{nickname}/command endpoint. Instead, we render copy-pastable CLI snippets that the operator runs from their shell — the token never leaves the CLI's environment. #}
CLI actions (copy-paste)
aisctl fleet push {{ poll.nickname }} purge
aisctl fleet push {{ poll.nickname }} restart --engine <engine>
aisctl fleet push {{ poll.nickname }} unload --engine <engine> --model <name>
aisctl fleet push {{ poll.nickname }} load --engine ollama --model <name>
aisctl fleet push @all purge   # broadcast
{% endfor %}