feat(dashboard): add assistant playbook presets with rollback
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
let _fastTimer = null;
|
||||
let _slowTimer = null;
|
||||
let _dashboardClient = null;
|
||||
let _lastPlaybookRollbackPatches = null;
|
||||
|
||||
function formatUptime(seconds) {
|
||||
const d = Math.floor(seconds / 86400);
|
||||
@@ -55,6 +56,71 @@ function escapeHtml(str) {
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function getAssistantStateSnapshot(configData) {
|
||||
const automation = configData?.automation ?? {};
|
||||
const memory = configData?.memory ?? {};
|
||||
const tts = configData?.tts ?? {};
|
||||
const queue = configData?.server?.queue ?? {};
|
||||
return {
|
||||
announce: (automation.delivery_mode ?? 'shared_session') === 'announce',
|
||||
dailyBriefing: Boolean(automation.daily_briefing?.enabled),
|
||||
memoryDaily: Boolean(memory.daily_log?.enabled),
|
||||
memoryProactive: Boolean(memory.proactive_extract?.enabled),
|
||||
memoryMinToolCalls: Number(memory.proactive_extract?.min_tool_calls ?? 1),
|
||||
ttsEnabled: Boolean(tts.enabled),
|
||||
ttsChannels: Array.isArray(tts.enabled_channels) ? tts.enabled_channels : [],
|
||||
queueMode: queue.mode ?? 'collect',
|
||||
};
|
||||
}
|
||||
|
||||
function buildPlaybookPatches(playbook) {
|
||||
if (playbook === 'executive') {
|
||||
return {
|
||||
'automation.delivery_mode': 'announce',
|
||||
'automation.daily_briefing.enabled': true,
|
||||
'memory.daily_log.enabled': true,
|
||||
'memory.proactive_extract.enabled': true,
|
||||
'memory.proactive_extract.min_tool_calls': 1,
|
||||
'tts.enabled': true,
|
||||
'tts.enabled_channels': [],
|
||||
'server.queue.mode': 'interrupt',
|
||||
};
|
||||
}
|
||||
if (playbook === 'operator') {
|
||||
return {
|
||||
'automation.delivery_mode': 'announce',
|
||||
'automation.daily_briefing.enabled': true,
|
||||
'memory.daily_log.enabled': true,
|
||||
'memory.proactive_extract.enabled': true,
|
||||
'memory.proactive_extract.min_tool_calls': 2,
|
||||
'tts.enabled': false,
|
||||
'server.queue.mode': 'steer_backlog',
|
||||
};
|
||||
}
|
||||
return {
|
||||
'automation.delivery_mode': 'shared_session',
|
||||
'automation.daily_briefing.enabled': false,
|
||||
'memory.daily_log.enabled': false,
|
||||
'memory.proactive_extract.enabled': false,
|
||||
'memory.proactive_extract.min_tool_calls': 3,
|
||||
'tts.enabled': false,
|
||||
'server.queue.mode': 'collect',
|
||||
};
|
||||
}
|
||||
|
||||
function buildRollbackPatchesFromSnapshot(snapshot) {
|
||||
return {
|
||||
'automation.delivery_mode': snapshot.announce ? 'announce' : 'shared_session',
|
||||
'automation.daily_briefing.enabled': snapshot.dailyBriefing,
|
||||
'memory.daily_log.enabled': snapshot.memoryDaily,
|
||||
'memory.proactive_extract.enabled': snapshot.memoryProactive,
|
||||
'memory.proactive_extract.min_tool_calls': Number.isFinite(snapshot.memoryMinToolCalls) ? snapshot.memoryMinToolCalls : 1,
|
||||
'tts.enabled': snapshot.ttsEnabled,
|
||||
'tts.enabled_channels': snapshot.ttsChannels,
|
||||
'server.queue.mode': snapshot.queueMode,
|
||||
};
|
||||
}
|
||||
|
||||
// ── Initial full render ─────────────────────────────────────────
|
||||
|
||||
function renderSkeleton(el) {
|
||||
@@ -490,6 +556,8 @@ function updateAssistantHealth(configData) {
|
||||
const el = document.getElementById('ops-assistant-health');
|
||||
if (!el) {return;}
|
||||
|
||||
const snapshot = getAssistantStateSnapshot(configData);
|
||||
|
||||
const automation = configData?.automation ?? {};
|
||||
const memory = configData?.memory ?? {};
|
||||
const tts = configData?.tts ?? {};
|
||||
@@ -549,6 +617,24 @@ function updateAssistantHealth(configData) {
|
||||
${ttsEnabled ? 'Disable TTS' : 'Enable TTS'}
|
||||
</button>
|
||||
</div>
|
||||
<div class="assistant-playbooks">
|
||||
<div class="assistant-preview-title">Assistant Playbooks</div>
|
||||
<div class="assistant-playbook-grid">
|
||||
<button class="btn btn-secondary assistant-action-btn" data-action="playbook-executive">
|
||||
Executive
|
||||
</button>
|
||||
<button class="btn btn-secondary assistant-action-btn" data-action="playbook-operator">
|
||||
Operator
|
||||
</button>
|
||||
<button class="btn btn-secondary assistant-action-btn" data-action="playbook-focus">
|
||||
Focus
|
||||
</button>
|
||||
<button class="btn btn-secondary assistant-action-btn" data-action="playbook-undo" ${_lastPlaybookRollbackPatches ? '' : 'disabled'}>
|
||||
Undo Last Playbook
|
||||
</button>
|
||||
</div>
|
||||
<div class="text-sm text-muted">Executive: announce + voice + aggressive interrupt. Operator: announce + memory-first + steer backlog. Focus: reactive, quieter mode.</div>
|
||||
</div>
|
||||
<div class="assistant-preview">
|
||||
<div class="assistant-preview-header">
|
||||
<div class="assistant-preview-title">Morning Brief Preview</div>
|
||||
@@ -588,6 +674,25 @@ function updateAssistantHealth(configData) {
|
||||
} else if (action === 'test-daily-briefing') {
|
||||
await triggerDailyBriefingTest(briefingName, statusEl);
|
||||
return;
|
||||
} else if (action === 'playbook-executive') {
|
||||
_lastPlaybookRollbackPatches = buildRollbackPatchesFromSnapshot(snapshot);
|
||||
patches = buildPlaybookPatches('executive');
|
||||
} else if (action === 'playbook-operator') {
|
||||
_lastPlaybookRollbackPatches = buildRollbackPatchesFromSnapshot(snapshot);
|
||||
patches = buildPlaybookPatches('operator');
|
||||
} else if (action === 'playbook-focus') {
|
||||
_lastPlaybookRollbackPatches = buildRollbackPatchesFromSnapshot(snapshot);
|
||||
patches = buildPlaybookPatches('focus');
|
||||
} else if (action === 'playbook-undo') {
|
||||
if (!_lastPlaybookRollbackPatches) {
|
||||
if (statusEl) {
|
||||
statusEl.textContent = 'No playbook changes to undo.';
|
||||
statusEl.className = 'text-sm text-muted';
|
||||
}
|
||||
return;
|
||||
}
|
||||
patches = _lastPlaybookRollbackPatches;
|
||||
_lastPlaybookRollbackPatches = null;
|
||||
}
|
||||
if (!patches) {return;}
|
||||
await applyAssistantPatch(patches, statusEl);
|
||||
@@ -758,5 +863,6 @@ export const DashboardPage = {
|
||||
_lastHealth = null;
|
||||
_lastMetrics = null;
|
||||
_dashboardClient = null;
|
||||
_lastPlaybookRollbackPatches = null;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1579,6 +1579,21 @@ tr:hover td {
|
||||
background-color: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.assistant-playbooks {
|
||||
margin-top: 12px;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
background-color: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.assistant-playbook-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 8px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.assistant-preview-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
Reference in New Issue
Block a user