feat: drawer edits for edge_trust / edge_summary / memory_pov_summary / knowledge_facts (T72.1)

Adds the four POST routes whose state-layer support was already
dispatched by the manual_edit projector (edge_trust, edge_summary,
memory_pov_summary) plus a new edge_knowledge_fact dispatch branch for
add/remove fact list manipulation. Drawer template gains editable
textareas, sliders, and add/remove fact controls. Remove semantics on
knowledge_fact match by string (not index) so concurrent edge_update
events appending facts between drawer renders don't desync the form.
This commit is contained in:
Joseph Doherty
2026-04-26 17:24:24 -04:00
parent 789b9bd042
commit 21404a373b
4 changed files with 685 additions and 18 deletions
+93 -7
View File
@@ -156,19 +156,95 @@
</label>
<button type="submit">Save</button>
</form>
{% if edge_b2y.summary %}<p class="muted">{{ edge_b2y.summary }}</p>{% endif %}
{% if edge_b2y.knowledge %}
<details><summary>Knowledge ({{ edge_b2y.knowledge|length }})</summary>
<ul>{% for fact in edge_b2y.knowledge %}<li>{{ fact }}</li>{% endfor %}</ul>
</details>
{% endif %}
<form class="inline-edit"
hx-post="/chats/{{ chat.id }}/drawer/edge/trust"
hx-target="#drawer" hx-swap="innerHTML">
<input type="hidden" name="source_id" value="{{ host_bot.id }}">
<input type="hidden" name="target_id" value="you">
<label>
Trust:
<input type="range" name="new_value" min="0" max="100"
value="{{ edge_b2y.trust }}"
oninput="this.nextElementSibling.value = this.value">
<output>{{ edge_b2y.trust }}</output>
</label>
<button type="submit">Save</button>
</form>
<form class="inline-edit"
hx-post="/chats/{{ chat.id }}/drawer/edge/summary"
hx-target="#drawer" hx-swap="innerHTML">
<input type="hidden" name="source_id" value="{{ host_bot.id }}">
<input type="hidden" name="target_id" value="you">
<label>
Summary:
<textarea name="new_summary" rows="3" maxlength="2000">{{ edge_b2y.summary or "" }}</textarea>
</label>
<button type="submit">Save summary</button>
</form>
<details>
<summary>Knowledge ({{ (edge_b2y.knowledge or [])|length }})</summary>
{% if edge_b2y.knowledge %}
<ul>
{% for fact in edge_b2y.knowledge %}
<li>
{{ fact }}
<form class="inline-edit"
hx-post="/chats/{{ chat.id }}/drawer/edge/knowledge-facts"
hx-target="#drawer" hx-swap="innerHTML">
<input type="hidden" name="source_id" value="{{ host_bot.id }}">
<input type="hidden" name="target_id" value="you">
<input type="hidden" name="action" value="remove">
<input type="hidden" name="fact" value="{{ fact }}">
<button type="submit">Remove</button>
</form>
</li>
{% endfor %}
</ul>
{% endif %}
<form class="inline-edit"
hx-post="/chats/{{ chat.id }}/drawer/edge/knowledge-facts"
hx-target="#drawer" hx-swap="innerHTML">
<input type="hidden" name="source_id" value="{{ host_bot.id }}">
<input type="hidden" name="target_id" value="you">
<input type="hidden" name="action" value="add">
<label>
Add fact:
<input type="text" name="fact" maxlength="500" required>
</label>
<button type="submit">Add</button>
</form>
</details>
</div>
{% endif %}
{% if edge_y2b %}
<div class="edge-row">
<strong>you &rarr; {{ host_bot.name }}</strong>
<p>Affinity: {{ edge_y2b.affinity }}/100 &middot; Trust: {{ edge_y2b.trust }}/100</p>
{% if edge_y2b.summary %}<p class="muted">{{ edge_y2b.summary }}</p>{% endif %}
<form class="inline-edit"
hx-post="/chats/{{ chat.id }}/drawer/edge/trust"
hx-target="#drawer" hx-swap="innerHTML">
<input type="hidden" name="source_id" value="you">
<input type="hidden" name="target_id" value="{{ host_bot.id }}">
<label>
Trust:
<input type="range" name="new_value" min="0" max="100"
value="{{ edge_y2b.trust }}"
oninput="this.nextElementSibling.value = this.value">
<output>{{ edge_y2b.trust }}</output>
</label>
<button type="submit">Save</button>
</form>
<form class="inline-edit"
hx-post="/chats/{{ chat.id }}/drawer/edge/summary"
hx-target="#drawer" hx-swap="innerHTML">
<input type="hidden" name="source_id" value="you">
<input type="hidden" name="target_id" value="{{ host_bot.id }}">
<label>
Summary:
<textarea name="new_summary" rows="3" maxlength="2000">{{ edge_y2b.summary or "" }}</textarea>
</label>
<button type="submit">Save summary</button>
</form>
</div>
{% endif %}
{% if not edge_b2y and not edge_y2b %}
@@ -224,6 +300,16 @@
<input type="hidden" name="pinned" value="{{ 0 if m.pinned else 1 }}">
<button type="submit">{{ 'Unpin' if m.pinned else 'Pin' }}</button>
</form>
<details>
<summary>Edit POV summary</summary>
<form class="inline-edit"
hx-post="/chats/{{ chat.id }}/drawer/memory/pov-summary"
hx-target="#drawer" hx-swap="innerHTML">
<input type="hidden" name="memory_id" value="{{ m.id }}">
<textarea name="new_summary" rows="3" maxlength="2000">{{ m.pov_summary }}</textarea>
<button type="submit">Save</button>
</form>
</details>
</li>
{% endfor %}
</ul>