forked from Rockachopa/Timmy-time-dashboard
feat: add task queue with human-in-the-loop approval + work orders + UI bug fixes
Task Queue system: - New /tasks page with three-column layout (Pending/Active/Completed) - Full CRUD API at /api/tasks with approve/veto/modify/pause/cancel/retry - SQLite persistence in task_queue table - WebSocket live updates via ws_manager - Create task modal with agent assignment and priority - Auto-approve rules for low-risk tasks - HTMX polling for real-time column updates - HOME TASK buttons now link to task queue with agent pre-selected - MARKET HIRE buttons link to task queue with agent pre-selected Work Order system: - External submission API for agents/users (POST /work-orders/submit) - Risk scoring and configurable auto-execution thresholds - Dashboard at /work-orders/queue with approve/reject/execute flow - Integration with swarm task system for execution UI & Dashboard bug fixes: - EVENTS: add startup event so page is never empty - LEDGER: fix empty filter params in URL - MISSION CONTROL: LLM backend and model now read from /health - MISSION CONTROL: agent count fallback to /swarm/agents - SWARM: HTMX fallback loads initial data if WebSocket is slow - MEMORY: add edit/delete buttons for personal facts - UPGRADES: add empty state guidance with links - BRIEFING: add regenerate button and POST /briefing/regenerate endpoint Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -105,9 +105,13 @@
|
||||
|
||||
<div class="mc-facts-list">
|
||||
{% if facts %}
|
||||
<ul class="mc-fact-list">
|
||||
<ul class="mc-fact-list" style="list-style: none; padding: 0;">
|
||||
{% for fact in facts %}
|
||||
<li class="memory-fact">{{ fact }}</li>
|
||||
<li class="memory-fact" id="fact-{{ fact.id }}" style="display:flex; align-items:center; gap:8px; padding:6px 0; border-bottom:1px solid rgba(255,255,255,0.08);">
|
||||
<span class="fact-content" style="flex:1;">{{ fact.content }}</span>
|
||||
<button class="mc-btn mc-btn-small" onclick="editFact('{{ fact.id }}', this)" style="font-size:0.7rem; padding:2px 8px;">EDIT</button>
|
||||
<button class="mc-btn mc-btn-small" onclick="deleteFact('{{ fact.id }}')" style="font-size:0.7rem; padding:2px 8px; color:#ef4444;">DEL</button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
@@ -116,4 +120,40 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function deleteFact(id) {
|
||||
if (!confirm('Delete this fact?')) return;
|
||||
fetch('/memory/fact/' + id, { method: 'DELETE' })
|
||||
.then(function(r) { if (r.ok) document.getElementById('fact-' + id).remove(); });
|
||||
}
|
||||
function editFact(id, btn) {
|
||||
var li = document.getElementById('fact-' + id);
|
||||
var span = li.querySelector('.fact-content');
|
||||
var current = span.textContent.trim();
|
||||
var input = document.createElement('input');
|
||||
input.type = 'text'; input.value = current;
|
||||
input.className = 'mc-input'; input.style.flex = '1';
|
||||
span.replaceWith(input);
|
||||
btn.textContent = 'SAVE';
|
||||
btn.onclick = function() {
|
||||
var val = input.value.trim();
|
||||
if (!val) return;
|
||||
fetch('/memory/fact/' + id, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ content: val })
|
||||
}).then(function(r) {
|
||||
if (r.ok) {
|
||||
var newSpan = document.createElement('span');
|
||||
newSpan.className = 'fact-content'; newSpan.style.flex = '1';
|
||||
newSpan.textContent = val;
|
||||
input.replaceWith(newSpan);
|
||||
btn.textContent = 'EDIT';
|
||||
btn.onclick = function() { editFact(id, btn); };
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user