daybook/templates/artifacts/settings_api_keys.html
peter d30e2436ab v0.3.0: rename app Daybook -> AgentFeed
Removes the "Daybook" name from everything user- and agent-facing, since no
agents are configured yet and this is the cheap moment to do it.

- UI brand, docs, README, CLAUDE.md -> AgentFeed.
- Ingest env vars DAYBOOK_URL/TOKEN/SOURCE/DATA_DIR/BIND_ADDR/HOST_DATA_DIR/
  KEY_PROVISIONING_API -> AGENTFEED_* (token *values* unchanged).
- Skill: skills/daybook-posting -> skills/agentfeed-posting, daybook_post.py
  -> agentfeed_post.py (+ scripts/ wrapper and its test).
- static/daybook.css -> static/agentfeed.css; localStorage daybook.* ->
  agentfeed.*; templatetag daybook_extras -> agentfeed_extras; multipart
  boundaries; json/csv viewer element ids; daybook_exception_handler ->
  agentfeed_exception_handler; compose service/container -> agentfeed.
- Key-provisioning API now OFF by default (independent of DEBUG); enable with
  AGENTFEED_KEY_PROVISIONING_API=1 on test installs only.
- Posting helper now points at Settings -> API Keys.

Deferred on purpose (a later, separate step): the Django package
`daybook_project`, the `/opt/daybook` install path, and the Forgejo repo name.
The sibling AGENT_DAYBOOK__LLM_TEST name is intentionally untouched.

Full suite: 129 passing; live server verified serving under the new name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-04 13:10:28 +01:00

66 lines
2.4 KiB
HTML

{% extends "artifacts/settings_base.html" %}
{% block settings_content %}
<h2>API Keys</h2>
<p>
One key per agent or script. Name each key so you know which agent it's
for, copy it into that agent's <code>AGENTFEED_TOKEN</code>, and revoke keys
individually here. Use a key as
<code>Authorization: Bearer &lt;key&gt;</code> when posting.
</p>
<h3>Create a key</h3>
<form method="post" class="api-key-create">
{% csrf_token %}
<input type="hidden" name="action" value="create">
<label>Name <input type="text" name="name" placeholder="e.g. hermes-agent" required autocomplete="off"></label>
<button type="submit">Create key</button>
</form>
<h3>Your keys</h3>
{% if api_keys %}
<table class="api-key-table">
<thead>
<tr><th>Name</th><th>Key</th><th>Created</th><th>Last used</th><th></th></tr>
</thead>
<tbody>
{% for k in api_keys %}
<tr>
<td>{{ k.name }}</td>
<td class="api-key-cell">
<code class="token-value">{{ k.key }}</code>
<button type="button" class="api-key-copy" data-copy="{{ k.key }}">Copy</button>
</td>
<td>{{ k.created_at|date:"Y-m-d" }}</td>
<td>{% if k.last_used_at %}{{ k.last_used_at|date:"Y-m-d H:i" }}{% else %}<span class="muted">never</span>{% endif %}</td>
<td>
<form method="post" onsubmit="return confirm('Revoke key &quot;{{ k.name|escapejs }}&quot;? Agents using it will stop working immediately.');">
{% csrf_token %}
<input type="hidden" name="action" value="revoke">
<input type="hidden" name="key_id" value="{{ k.pk }}">
<button type="submit" class="api-key-revoke">Revoke</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="muted">No keys yet. Create one above.</p>
{% endif %}
<script>
(() => {
document.querySelectorAll(".api-key-copy").forEach((btn) => {
btn.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(btn.dataset.copy);
const prev = btn.textContent;
btn.textContent = "Copied";
setTimeout(() => { btn.textContent = prev; }, 1200);
} catch (e) { /* clipboard unavailable; the key is visible to select manually */ }
});
});
})();
</script>
{% endblock %}