{% extends "base.html" %} {% from "icons.html" import icon, sep %} {% from "ui.html" import action, when with context %} {% from "tidy-run-now.html" import run_now_button with context %} {% set tab = 'tidy' %} {% block title %}{{ _("Tidy-up") }} · {{ space.name }} · Synaptane{% endblock %} {% block crumbs %}{{ sep() }}{{ org.name }}{{ sep() }}{{ space.name }}{{ sep() }}{{ _("Tidy-up") }}{% endblock %} {% block content %} {% set space_tab = "tidy" %}{% include "space-tabs.html" %} {% set base = "/o/" ~ org.slug ~ "/" ~ space.slug %} {% set triggers = {'schedule': _("scheduled"), 'chain': _("chained"), 'manual': _("manual")} %} {# Header: when the tidy-up runs, and running it by hand. The button is subdued when the run is very likely to fail; it asks for confirmation if it costs money. #}

{{ _("Tidy-up") }}

{% if space.tidy_enabled %}{{ _("Every day at {time} ({tz})", time=space.tidy_time, tz=space.tidy_timezone) }}{% else %}{{ _("Automatic tidy-up turned off") }}{% endif %}{% if manage %} · {{ _("Edit") }}{% endif %} {% set upcoming = tidy_next_label(space) %}{% if upcoming %}{{ upcoming }}{% endif %}

{% if contribute and configured %}
{{ run_now_button(base ~ "/-/tidy", caution, paid, average_cost) }} {% if caution == 'failures' %}

{{ _("The last {n} runs failed: test the connection first.", n=streak.count) }}

{% elif caution == 'test' %}

{{ _("The last connection test failed: test it again before starting a run.") }}{% if manage %} {{ _("Organization AI page") }}{% endif %}

{% endif %}
{% endif %}
{% if not configured %}

{{ _("No AI provider is configured for the organization: the tidy-up cannot run.") }} {% if manage %}{{ _("Configure AI") }}{% else %}{{ _("Ask an organization administrator.") }}{% endif %}

{% elif streak %} {# Banner: the tidy-up fails. To admins, the cause and what to do; to others, that it is broken and who is notified (the technical detail is of no use to them). #} {% set why = streak.explanation %}
{% if manage %}

{% if streak.count == 1 %}{{ _("The last run failed") }}{% else %}{{ (_("The tidy-up has been failing since {date} ({n} attempts)")|e).format(date=when(streak.since, 'date'), n=streak.count) }}{% endif %}

{{ _(why.message, **why.params) }}

{% if why.show_detail %}

{{ _("Technical detail: {detail}", detail=why.detail) }}

{% endif %} {# Repository not synchronized, or unrecognized cause while the Git repository has a problem: that is what to look at, testing the AI connection would change nothing. Nor for the other causes on Synaptane's side (busy space, stopped worker…). #} {% if why.code == 'not_synced' or (why.code in ('other', 'unknown') and space.sync_status != 'ok') %}
{{ _("See the repository status") }}
{% elif why.about_ai %}
{% if why.code not in ('budget', 'no_provider') %}{{ action("/o/" ~ org.slug ~ "/-/ai/test", _("Test the connection")) }}{% endif %} {{ _("Check the organization's AI") }}
{% endif %} {% else %}

{% if streak.count == 1 %}{{ _("The last tidy-up run failed.") }}{% else %}{{ (_("The tidy-up has been broken since {date}.")|e).format(date=when(streak.since, 'date')) }}{% endif %}

{% if streak.notified %}{{ _("The organization's administrators have been notified.") }}{% elif admins %}{{ _("Let an administrator of the organization know: {names}.", names=admins|join(", ")) }}{% else %}{{ _("Let an administrator of the organization know.") }}{% endif %}

{{ _("Cause: {cause}.", cause=_(why.label)) }}

{% endif %}
{% endif %} {% if spending.exhausted %}

{{ _("Monthly AI budget reached ({spent} of {budget}): the tidy-up is paused until next month.", spent=spending.spent|euros, budget=spending.budget|euros) }} {% if manage %}{{ _("Raise the budget") }}{% endif %}

{% elif spending.budget and spending.ratio >= 0.8 %}
{{ _("Monthly AI budget almost reached: {spent} of {budget}.", spent=spending.spent|euros, budget=spending.budget|euros) }}
{% endif %} {% if activity and activity.poll %}{% endif %}
{# Request not logged yet: the card appears on click, the page waits for the result. #} {% if activity and not activity.run %}

{% if activity.state == 'retry' %}{{ _("Retry scheduled") }}{% elif activity.state == 'running' %}{{ _("Running…") }}{% else %}{{ _("Waiting for the worker") }}{% endif %}

{% if activity.state == 'retry' %}{{ (_("The previous attempt failed; next try on {when}.")|e).format(when=when(activity.at)) }}{% elif activity.stalled %}{{ (_("Requested on {when}: the worker has not picked it up yet.")|e).format(when=when(activity.at)) }}{% else %}{{ _("The run starts as soon as the worker is free.") }}{% endif %}

{% if activity.stalled and manage %}

{{ _("Check that the worker is running (“worker” container, “synaptane worker” command).") }}

{% endif %}
{% endif %} {% for entry in entries %}{% set run = entry.run %}{% set why = entry.explanation %}

{%- if run.status == 'running' %}{{ _("Running…") }} {%- elif run.status == 'failed' %}{{ _("Failed · {cause}", cause=_(why.label)) }} {%- elif run.status == 'nothing' %}{{ _("Nothing to tidy") }} {%- elif run.items_done and run.items_left %}{{ _(pl(run.items_done, "{n} item filed", "{n} items filed"), n=run.items_done) }}, {{ _("{n} left in the inbox", n=run.items_left) }} {%- elif run.items_done %}{{ _(pl(run.items_done, "{n} item filed", "{n} items filed"), n=run.items_done) }} {%- elif run.items_left %}{{ _(pl(run.items_left, "{n} item left in the inbox", "{n} items left in the inbox"), n=run.items_left) }} {%- else %}{{ _("No item filed") }}{% endif -%}

{{ when(run.started_at) }} · {{ triggers.get(run.trigger, run.trigger) }}{% if entry.grouped %} · {{ _(pl(entry.attempts|length, "{n} attempt", "{n} attempts, all failed"), n=entry.attempts|length) }}{% endif %}

{% if run.reverted_at %}{{ _("undone") }}{% endif %}
{% if run.status == 'done' and run.summary %}

{{ run.summary }}

{% endif %} {% if why %}
{% if manage %}

{% if run.status != 'failed' %}{{ _("Run interrupted, work done so far kept.") }} {% endif %}{{ _(why.message, **why.params) }}

{# The banner already gives the detail of the last failure: no need to repeat it. #} {% if why.show_detail and not (streak and why.detail == streak.explanation.detail) %}

{{ _("Technical detail: {detail}", detail=why.detail) }}

{% endif %} {% else %}

{% if run.status != 'failed' %}{{ _("Run interrupted, work done so far kept.") }} {% endif %}{{ _("Cause: {cause}.", cause=_(why.label)) }}

{% endif %}
{% endif %} {% include "tidy-metrics.html" %} {% if entry.grouped %}
{{ _("Show the {n} attempts", n=entry.attempts|length) }}
    {% for attempt in entry.attempts %}
  1. {{ when(attempt.started_at) }}
  2. {% endfor %}
{% endif %} {% if entry.operations %}
{{ _("Operations: {count}", count=entry.operations|length) }}
    {% for op in entry.operations %}
  • {{ op.op|operation_label }} {% if op.linked %}{{ op.path }}{% else %}{{ log_text(op.path) }}{% endif %} {%- if op.detail %} — {{ log_text(op.detail) }}{% endif %} {%- if op.pages %}{{ _("Integrated into:") }} {% for path in op.pages %}{{ path }}{% if not loop.last %}, {% endif %}{% endfor %} {%- elif op.no_page %}{{ _("No page given by the agent.") }}{% endif %}
  • {% endfor %}
{% endif %} {% if run.status != 'running' and (run.model or entry.tokens or run.commit) %}
{% if run.model %}{{ _("Model: {model}", model=run.model) }} · {% endif %}{{ _(pl(entry.tokens, "{n} token", "{n} tokens"), n="{:,}".format(entry.tokens).replace(",", " ")) }}{% if entry.cost is not none %} · {{ _("≈ {amount}", amount=entry.cost|euros) }}{% endif %}{% if run.quota %} · {{ _("subscription quota: {usage}", usage=run.quota|quota_summary) }}{% endif %}{% if run.commit %} · {{ run.commit[:10] }}{% endif %} {% if run.commit %}
{{ _("Pages changed") if not contribute or run.reverted_at else _("Undo some pages…") }} {% if manage and not run.reverted_at %}{{ action(base ~ "/-/tidy/" ~ run.id ~ "/revert", _("Undo this run"), confirm=_("Undo this run? Its changes are removed from the wiki and the tidied items return to the inbox."), kind="danger") }}{% endif %}
{% endif %}
{% endif %}
{% else %} {% if not activity %}

{{ _("No runs yet.") }}

{% endif %} {% endfor %}
{% endblock %}