feat: add AI markdown reformatting and usage metering to NewsService

Add AI-powered body reformatting for valid articles in the news pipeline, converting raw text walls into clean Markdown with paragraphs, headings, and lists. Introduce `news_usage` database table and `add_news_usage`/`get_news_usage` helpers to track per-cycle gateway costs (calls, tokens, latency, USD) from response headers, reported on the admin Services page. Remove unused `.sidebar-more` CSS and apply `render_title()` to poll question/label fields.
This commit is contained in:
2026-06-18 23:46:53 +00:00
parent 6ceca3d0d4
commit f3a4667fce
13 changed files with 427 additions and 57 deletions
+2 -2
View File
@@ -1,11 +1,11 @@
{% if _poll %}
<div class="poll" data-poll-uid="{{ _poll.uid }}">
<div class="poll-question">{{ _poll.question }}</div>
<div class="poll-question">{{ render_title(_poll.question) }}</div>
<div class="poll-options" role="group" aria-label="Poll options">
{% for opt in _poll.options %}
<button type="button" class="poll-option{% if _poll.my_choice == opt.uid %} chosen{% endif %}" data-option-uid="{{ opt.uid }}" aria-pressed="{% if _poll.my_choice == opt.uid %}true{% else %}false{% endif %}"{{ guest_disabled(user) }}>
<span class="poll-option-bar" style="width: {{ opt.pct }}%;"></span>
<span class="poll-option-label">{{ opt.label }}</span>
<span class="poll-option-label">{{ render_title(opt.label) }}</span>
<span class="poll-option-meta">
<span class="poll-option-check"{% if _poll.my_choice != opt.uid %} hidden{% endif %}>&#x2713;</span>
<span class="poll-option-pct">{{ opt.pct }}%</span>