feat: update dependencies and enhance chat functionality
- Added new Radix UI components including checkbox, label, popover, slider, switch, and tooltip to improve UI interactions. - Integrated react-syntax-highlighter for better code rendering in chat messages. - Updated package.json and pnpm-lock.yaml to include new dependencies and ensure compatibility. - Enhanced chat input to support web search toggling, improving user experience during message composition. - Implemented auto-saving of chat sessions and improved session management features. - Refactored chat message rendering to clean up metadata and improve display quality.
This commit is contained in:
1 parent
032722e21b
commit
8834ef2b4f
55 files changed
+20030
-159
No files matched your search
@@ -0,0 +1,309 @@
|
||||
# Guia de Implementação: System Tray, Background Mode e Task Scheduler
|
||||
|
||||
## Status da Implementação
|
||||
|
||||
### ✅ Concluído
|
||||
|
||||
1. **Estrutura de Tasks** (`src-tauri/src/scheduler.rs`)
|
||||
- `SentinelTask` com suporte a múltiplos tipos de ações
|
||||
- Persistência em `tasks.json`
|
||||
- Gerenciamento de estado thread-safe
|
||||
|
||||
2. **Cliente Ollama Headless** (`src-tauri/src/ollama_client.rs`)
|
||||
- Comunicação direta com Ollama via `reqwest`
|
||||
- Suporte a streaming
|
||||
- Verificação de conexão
|
||||
|
||||
3. **Executor de Tasks** (`src-tauri/src/task_executor.rs`)
|
||||
- Execução de `SearchAndSummarize`
|
||||
- Execução de `JustPing`
|
||||
- Execução de `CustomPrompt`
|
||||
- Integração com file locks para escrita segura
|
||||
|
||||
4. **Scheduler Loop** (`src-tauri/src/scheduler_loop.rs`)
|
||||
- Integração com `tokio-cron-scheduler`
|
||||
- Recarregamento dinâmico de tasks
|
||||
- Execução assíncrona em background
|
||||
|
||||
### 🔨 Pendente (Próximos Passos)
|
||||
|
||||
#### 1. Comandos Tauri para CRUD de Tasks
|
||||
|
||||
Adicione ao `src-tauri/src/lib.rs`:
|
||||
|
||||
```rust
|
||||
use scheduler::{SchedulerService, SchedulerState, SentinelTask, TaskAction};
|
||||
use chrono::Utc;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[command]
|
||||
async fn create_task(
|
||||
scheduler: State<'_, SchedulerState>,
|
||||
label: String,
|
||||
cron_schedule: String,
|
||||
action: TaskAction,
|
||||
) -> Result<String, String> {
|
||||
let task = SentinelTask {
|
||||
id: Uuid::new_v4().to_string(),
|
||||
label,
|
||||
cron_schedule,
|
||||
action,
|
||||
enabled: true,
|
||||
last_run: None,
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
};
|
||||
|
||||
let mut sched = scheduler.lock().await;
|
||||
sched.upsert_task(task.clone())?;
|
||||
Ok(task.id)
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn list_tasks(
|
||||
scheduler: State<'_, SchedulerState>,
|
||||
) -> Result<Vec<SentinelTask>, String> {
|
||||
let sched = scheduler.lock().await;
|
||||
Ok(sched.list_tasks())
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn update_task(
|
||||
scheduler: State<'_, SchedulerState>,
|
||||
task: SentinelTask,
|
||||
) -> Result<(), String> {
|
||||
let mut sched = scheduler.lock().await;
|
||||
let mut updated = task;
|
||||
updated.updated_at = Utc::now();
|
||||
sched.upsert_task(updated)
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn delete_task(
|
||||
scheduler: State<'_, SchedulerState>,
|
||||
id: String,
|
||||
) -> Result<(), String> {
|
||||
let mut sched = scheduler.lock().await;
|
||||
sched.remove_task(&id)
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn toggle_task(
|
||||
scheduler: State<'_, SchedulerState>,
|
||||
id: String,
|
||||
enabled: bool,
|
||||
) -> Result<(), String> {
|
||||
let mut sched = scheduler.lock().await;
|
||||
if let Some(mut task) = sched.get_task(&id).cloned() {
|
||||
task.enabled = enabled;
|
||||
task.updated_at = Utc::now();
|
||||
sched.upsert_task(task)
|
||||
} else {
|
||||
Err("Task not found".to_string())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. System Tray Setup
|
||||
|
||||
No `src-tauri/src/lib.rs`, modifique o `.setup()`:
|
||||
|
||||
```rust
|
||||
use tauri::{Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem};
|
||||
|
||||
.setup(|app| {
|
||||
// ... código existente ...
|
||||
|
||||
// Criar System Tray
|
||||
let tray_menu = SystemTrayMenu::new()
|
||||
.add_item(SystemTrayMenuItem::with_id("show", "Mostrar OllaHub", true, None))
|
||||
.add_item(SystemTrayMenuItem::with_id("pause", "Pausar Tasks", true, None))
|
||||
.add_native_item(SystemTrayMenuItem::Separator)
|
||||
.add_item(SystemTrayMenuItem::with_id("quit", "Sair", true, None));
|
||||
|
||||
let system_tray = SystemTray::new().with_menu(tray_menu);
|
||||
|
||||
app.handle().system_tray(system_tray)?;
|
||||
|
||||
// Handler de eventos do Tray
|
||||
app.handle().on_system_tray_event(|app, event| {
|
||||
if let SystemTrayEvent::MenuItemClick { id, .. } = event {
|
||||
match id.as_str() {
|
||||
"show" => {
|
||||
if let Some(window) = app.get_window("main") {
|
||||
window.show().unwrap();
|
||||
window.set_focus().unwrap();
|
||||
}
|
||||
}
|
||||
"pause" => {
|
||||
// Implementar lógica de pausar tasks
|
||||
log::info!("Pausar tasks - implementar");
|
||||
}
|
||||
"quit" => {
|
||||
app.exit(0);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Modificar comportamento de fechar janela
|
||||
if let Some(window) = app.get_window("main") {
|
||||
window.on_window_event(|event| {
|
||||
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
|
||||
// Ocultar ao invés de fechar
|
||||
if let Some(window) = event.window() {
|
||||
window.hide().unwrap();
|
||||
}
|
||||
api.prevent_close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
```
|
||||
|
||||
#### 3. Inicializar Scheduler no Setup
|
||||
|
||||
No mesmo `.setup()`, após criar o scheduler:
|
||||
|
||||
```rust
|
||||
// Inicializar scheduler
|
||||
let scheduler_service = SchedulerService::new(app.handle().clone())?;
|
||||
let scheduler_state: SchedulerState = Arc::new(Mutex::new(scheduler_service));
|
||||
let browser_state: BrowserState = app.state();
|
||||
|
||||
// Iniciar loop do scheduler em background
|
||||
let app_handle = app.handle().clone();
|
||||
let scheduler_clone = scheduler_state.clone();
|
||||
let browser_clone = browser_state.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = scheduler_loop::start_scheduler_loop(
|
||||
app_handle,
|
||||
scheduler_clone,
|
||||
browser_clone,
|
||||
None, // Ollama URL - pode vir do settings
|
||||
).await {
|
||||
log::error!("Erro ao iniciar scheduler: {}", e);
|
||||
}
|
||||
});
|
||||
|
||||
// Adicionar ao manage
|
||||
.manage(scheduler_state)
|
||||
```
|
||||
|
||||
#### 4. Adicionar Comandos ao Invoke Handler
|
||||
|
||||
```rust
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
// ... comandos existentes ...
|
||||
create_task,
|
||||
list_tasks,
|
||||
update_task,
|
||||
delete_task,
|
||||
toggle_task,
|
||||
])
|
||||
```
|
||||
|
||||
#### 5. Interface React (app/tasks/page.tsx)
|
||||
|
||||
Crie uma página básica para gerenciar tasks:
|
||||
|
||||
```tsx
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
|
||||
interface Task {
|
||||
id: string;
|
||||
label: string;
|
||||
cron_schedule: string;
|
||||
action: any;
|
||||
enabled: boolean;
|
||||
last_run: string | null;
|
||||
}
|
||||
|
||||
export default function TasksPage() {
|
||||
const [tasks, setTasks] = useState<Task[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
loadTasks();
|
||||
}, []);
|
||||
|
||||
const loadTasks = async () => {
|
||||
try {
|
||||
const loaded = await invoke<Task[]>('list_tasks');
|
||||
setTasks(loaded);
|
||||
} catch (error) {
|
||||
console.error('Erro ao carregar tasks:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleTask = async (id: string, enabled: boolean) => {
|
||||
try {
|
||||
await invoke('toggle_task', { id, enabled: !enabled });
|
||||
await loadTasks();
|
||||
} catch (error) {
|
||||
console.error('Erro ao alternar task:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-6">
|
||||
<h1 className="text-2xl font-bold mb-4">Tarefas Agendadas</h1>
|
||||
<div className="space-y-4">
|
||||
{tasks.map(task => (
|
||||
<Card key={task.id}>
|
||||
<CardHeader>
|
||||
<CardTitle>{task.label}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p>Cron: {task.cron_schedule}</p>
|
||||
<p>Status: {task.enabled ? 'Ativa' : 'Pausada'}</p>
|
||||
<Button onClick={() => toggleTask(task.id, task.enabled)}>
|
||||
{task.enabled ? 'Pausar' : 'Ativar'}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Dependências Adicionais Necessárias
|
||||
|
||||
No `Cargo.toml`, já foram adicionadas:
|
||||
- `tokio-cron-scheduler = "0.9"`
|
||||
- `futures-util = "0.3"`
|
||||
- `tauri-plugin-notification = "2"`
|
||||
|
||||
**Nota para Linux:** Para System Tray funcionar, pode ser necessário:
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt-get install libappindicator3-1
|
||||
|
||||
# Arch/Manjaro
|
||||
sudo pacman -S libappindicator-gtk3
|
||||
```
|
||||
|
||||
## Próximos Passos
|
||||
|
||||
1. Compilar e testar: `cd src-tauri && cargo build`
|
||||
2. Corrigir erros de compilação
|
||||
3. Testar criação de task via frontend
|
||||
4. Verificar se scheduler executa corretamente
|
||||
5. Testar System Tray em diferentes plataformas
|
||||
|
||||
## Notas Importantes
|
||||
|
||||
- **File Locking**: Já implementado - tasks usam o mesmo sistema de locks que salvar sessões
|
||||
- **Concorrência**: Scheduler roda em thread separada, não bloqueia UI
|
||||
- **Persistência**: Tasks são salvas em `app_data_dir/tasks.json`
|
||||
- **Notificações**: Usa `tauri-plugin-notification` para notificações nativas
|
||||
|
||||
Reference in new issue
Block a user