wraith/src-tauri/src/commands/pty_commands.rs
Vantz Stockwell 512347af5f
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 3m6s
feat: Local PTY Copilot Panel — replace Gemini stub with real terminal
Ripped out the Gemini API stub (ai/mod.rs, ai_commands.rs, GeminiPanel.vue)
and replaced it with a local PTY terminal in the sidebar panel. Users select
a shell (bash/zsh/sh on Unix, PowerShell/CMD/Git Bash on Windows), launch it,
and run claude/gemini/codex or any CLI tool directly.

Backend:
- New PtyService module using portable-pty (cross-platform PTY)
- DashMap session registry (same pattern as SshService)
- spawn_blocking output loop (portable-pty reader is synchronous)
- 5 Tauri commands: list_available_shells, spawn_local_shell, pty_write,
  pty_resize, disconnect_pty

Frontend:
- Parameterized useTerminal composable: backend='ssh'|'pty'
- convertEol=false for PTY (PTY driver handles LF→CRLF)
- CopilotPanel.vue with shell selector, launch/kill, session ended prompt
- Ctrl+Shift+G toggle preserved

Tests: 87 total (5 new PTY tests), zero warnings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:43:18 -04:00

50 lines
1.1 KiB
Rust

//! Tauri commands for local PTY session management.
use tauri::{AppHandle, State};
use crate::pty::ShellInfo;
use crate::AppState;
#[tauri::command]
pub fn list_available_shells(state: State<'_, AppState>) -> Vec<ShellInfo> {
state.pty.list_shells()
}
#[tauri::command]
pub fn spawn_local_shell(
shell_path: String,
cols: u32,
rows: u32,
app_handle: AppHandle,
state: State<'_, AppState>,
) -> Result<String, String> {
state.pty.spawn(&shell_path, cols as u16, rows as u16, app_handle)
}
#[tauri::command]
pub fn pty_write(
session_id: String,
data: String,
state: State<'_, AppState>,
) -> Result<(), String> {
state.pty.write(&session_id, data.as_bytes())
}
#[tauri::command]
pub fn pty_resize(
session_id: String,
cols: u32,
rows: u32,
state: State<'_, AppState>,
) -> Result<(), String> {
state.pty.resize(&session_id, cols as u16, rows as u16)
}
#[tauri::command]
pub fn disconnect_pty(
session_id: String,
state: State<'_, AppState>,
) -> Result<(), String> {
state.pty.disconnect(&session_id)
}