feat: voice agent commands, cross-session memory, proactive reminders

- Voice commands (#3): say "restart the homebridge agent" or "restart mediastack agent" → queues restart_service to that agent; lists options if no hostname matched; 6 KB intents added
- Persistent context (#4): chat.php now loads last 6 turns from most recent prior session before current session history, giving JARVIS memory across page reloads
- Proactive reminders (#5): 3s after login, auto-announces overdue tasks / tasks due today / upcoming appointments; 5-min interval checks for appointments starting within 15 min and speaks alert once

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 02:23:48 +00:00
parent c74a9af8be
commit e381858299
2 changed files with 102 additions and 2 deletions
+54 -2
View File
@@ -72,13 +72,27 @@ JarvisDB::insert(
[$sessionId, 'user', $message]
);
// Conversation history
// Conversation history — current session
$history = JarvisDB::query(
'SELECT role, content FROM conversations WHERE session_id=? ORDER BY created_at DESC LIMIT 10',
[$sessionId]
);
) ?? [];
$history = array_reverse($history);
// Cross-session memory: last 6 turns from the most recent prior session
$priorSession = JarvisDB::query(
"SELECT session_id FROM conversations WHERE session_id != ? AND role='user'
ORDER BY created_at DESC LIMIT 1",
[$sessionId]
);
if ($priorSession && !empty($priorSession[0]['session_id'])) {
$priorHistory = JarvisDB::query(
'SELECT role, content FROM conversations WHERE session_id=? ORDER BY created_at DESC LIMIT 6',
[$priorSession[0]['session_id']]
) ?? [];
$history = array_merge(array_reverse($priorHistory), $history);
}
$reply = null;
$source = 'unknown';
@@ -1633,6 +1647,44 @@ if (!$reply) {
if ($matched && $matched['action'] === 'action') {
switch ($matched['intent']) {
case 'restart_agent':
// Extract target hostname from message
$msgLow = strtolower($message);
$agentMap = [
'homebridge' => 'homebridge_b57cbaea',
'jellyfin' => 'jellyfin_7e386833',
'networkbackup' => 'networkbackup_NetworkB',
'network backup'=> 'networkbackup_NetworkB',
'novacpx' => 'novacpx_e3b07264',
'nova' => 'novacpx_e3b07264',
'mediastack' => 'MediaStack_2c00b1b8',
'media stack' => 'MediaStack_2c00b1b8',
'homeassistant' => 'homeassistant_ha',
'home assistant'=> 'homeassistant_ha',
];
$targetAgentId = null;
$targetName = null;
foreach ($agentMap as $keyword => $agentId) {
if (str_contains($msgLow, $keyword)) {
$targetAgentId = $agentId;
$targetName = ucfirst($keyword);
break;
}
}
if ($targetAgentId) {
JarvisDB::insert(
"INSERT INTO agent_commands (agent_id, command_type, command_data, status, created_at)
VALUES (?, 'restart_service', ?, 'pending', NOW())",
[$targetAgentId, json_encode(['service' => 'jarvis-agent'])]
);
$reply = "Restart command sent to the {$targetName} agent, {$userAddr}. It should come back online within 15 seconds.";
} else {
// Fall back to listing restartable agents
$reply = "Which agent should I restart, {$userAddr}? I can restart: HomeAssistant, Homebridge, Jellyfin, MediaStack, NetworkBackup, or NovaCPX.";
}
$source = 'intent:restart_agent';
break;
case 'focus_mode':
$uiAction = 'focus_mode';
$reply = "Focus mode activated, {$userAddr}. Side panels hidden.";