{% comment %} Shared Agents fleet content. Included by: * fleet.html (standalone: inside scitex_ui/standalone_shell.html) * fleet_hub.html (Hub: inside global_base.html — no second header) `url_base` is the app's mount prefix ("" at root, "/apps/agents" when mounted) so the per-row links are correct in both modes. {% endcomment %}

Agents

{% if observed_age is not None %}Last known {{ observed_age|floatformat:0 }}s ago{% else %}Fleet{% endif %}
{{ summary.total }}visible
{{ summary.alive }}alive
{{ summary.attention }}need attention
{% if summary.cross_host %}
{{ summary.cross_host }}cross-host
{% endif %}
{% comment %} P0: this banner used to print the raw listener URL, the env-var names and a bearer-token instruction into the BROWSER. A browser must never receive an internal endpoint, a config key name, or deployment prose - that is operator information, and on a shared host it is an information leak. The user-facing copy is now state + Retry only; the diagnostic detail stays server-side. {% endcomment %} {% if fleet_state == "loading" %}
Loading the agent fleet

Reading the fleet…

{% endif %} {% if fleet_state == "unavailable" %} {% endif %} {% if fleet_state == "cached" %}
Showing the last known inventory{% if observed_age is not None %} from {{ observed_age|floatformat:0 }}s ago{% endif %}. This may be out of date; it refreshes automatically.
{% endif %}
acting as {{ identity|default:"(unidentified)" }} {% if crosshost_authorized %} cross-host fleet authorized {% else %} own-scope only {% endif %} {% if can_launch %} Launch agent {% endif %} A2A Activity
{% if agents %}
{% for a in agents %} {% endfor %}
AgentStateRuntimeBilling Auth identityHarnessEngine / Model ActivityHosta2a port Actions
{{ a.name }} {% if a.cross_host %}remote{% endif %} {{ a.state_label }} {{ a.runtime }} {{ a.billing_mode }} {{ a.auth_identity }} {{ a.harness }} {{ a.engine }} / {{ a.model }}{{ a.runtime_identity_source }} {% if a.activity.operation.state == "observed" %}{{ a.activity.operation.value }}{% else %}unknown{% endif %} {% if a.activity.phase.state == "observed" %} · {{ a.activity.phase.value }}{% endif %} {{ a.host }} {% if a.a2a_port %}{{ a.a2a_port }}{% else %}—{% endif %} inspect {% comment %} Per-row quick actions: the same Start/Restart/Stop POSTs the detail page offers (same /action route, same operator gate), plus a one-line message POST to /message. Gate mirrors the POST handlers exactly: own-scope rows need the lifecycle-operator list (`can_launch`), cross-host rows need the cross-host list (`can_control_crosshost`, decided once per render, not per row). {% endcomment %} {% if a.cross_host and can_control_crosshost or not a.cross_host and can_launch %}
{% if csrf_token %}{% endif %}
{% if csrf_token %}{% endif %}
{% endif %}
{% else %} {% if fleet_state == "empty" %}
No agents visible to {{ identity|default:"(unidentified)" }} in this scope.
{% endif %} {% endif %} {% comment %} B1: a cold shell renders as `loading`. This READ-ONLY poll warms the server's last-known snapshot via /api/fleet, then a single reload shows the true state (the inventory, or unavailable + Retry). It only fires while loading, stops after the one authoritative response, and issues only a GET - it never blocks first paint and never loops. (The Retry button above does the same reload.) {% endcomment %} {% if fleet_state == "loading" %} {% endif %}