mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-07-01 05:59:37 +00:00
Improved vt command to allow finding the current session
This commit is contained in:
parent
cbe5f87aed
commit
eee8a65450
4 changed files with 127 additions and 16 deletions
|
|
@ -27,6 +27,21 @@ find_claude() {
|
|||
return 1
|
||||
}
|
||||
|
||||
# Get the directory where this script is actually located (Resources folder)
|
||||
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_REAL_PATH")" && pwd)"
|
||||
|
||||
# Path to tty-fwd executable in the same Resources directory
|
||||
TTY_FWD="$SCRIPT_DIR/tty-fwd"
|
||||
|
||||
# Check if tty-fwd exists there, otherwise use the one from ../tty-fwd/target/debug/tty-fwd
|
||||
if [[ ! -x "$TTY_FWD" ]]; then
|
||||
TTY_FWD="$SCRIPT_DIR/../tty-fwd/target/debug/tty-fwd"
|
||||
if [[ ! -x "$TTY_FWD" ]]; then
|
||||
echo "Error: tty-fwd executable not found at $TTY_FWD" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Handle --claude option
|
||||
if [[ "$1" == "--claude" ]]; then
|
||||
shift
|
||||
|
|
@ -51,6 +66,18 @@ if [[ "$1" == "--claude-yolo" ]]; then
|
|||
exec "$0" "$claude_path" --dangerously-skip-permissions "$@"
|
||||
fi
|
||||
|
||||
# Handle --show-session-info option
|
||||
if [[ "$1" == "--show-session-info" ]]; then
|
||||
shift
|
||||
exec "$TTY_FWD" --show-session-info "$@"
|
||||
fi
|
||||
|
||||
# Handle --show-session-id option
|
||||
if [[ "$1" == "--show-session-id" ]]; then
|
||||
shift
|
||||
exec "$TTY_FWD" --show-session-id "$@"
|
||||
fi
|
||||
|
||||
# Handle --shell or -i option (launch current shell)
|
||||
if [[ "$1" == "--shell" || "$1" == "-i" ]]; then
|
||||
shift
|
||||
|
|
@ -76,6 +103,8 @@ USAGE:
|
|||
vt --shell [args...]
|
||||
vt -i [args...]
|
||||
vt --no-shell-wrap [command] [args...]
|
||||
vt --show-session-info
|
||||
vt --show-session-id
|
||||
vt -S [command] [args...]
|
||||
vt --help
|
||||
|
||||
|
|
@ -105,6 +134,8 @@ OPTIONS:
|
|||
--shell, -i Launch current shell (equivalent to vt $SHELL)
|
||||
--no-shell-wrap, -S Execute command directly without shell wrapper
|
||||
--help, -h Show this help message and exit
|
||||
--show-session-info Show current session info
|
||||
--show-session-id Show current session ID only
|
||||
|
||||
NOTE:
|
||||
This script automatically uses the tty-fwd executable bundled with
|
||||
|
|
@ -123,18 +154,6 @@ if [[ -z "$SCRIPT_REAL_PATH" ]]; then
|
|||
done
|
||||
fi
|
||||
|
||||
# Get the directory where this script is actually located (Resources folder)
|
||||
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_REAL_PATH")" && pwd)"
|
||||
|
||||
# Path to tty-fwd executable in the same Resources directory
|
||||
TTY_FWD="$SCRIPT_DIR/tty-fwd"
|
||||
|
||||
# Check if tty-fwd exists
|
||||
if [[ ! -x "$TTY_FWD" ]]; then
|
||||
echo "Error: tty-fwd executable not found at $TTY_FWD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to resolve command through user's shell
|
||||
resolve_command() {
|
||||
local user_shell="${SHELL:-/bin/bash}"
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
let mut stop = false;
|
||||
let mut kill = false;
|
||||
let mut cleanup = false;
|
||||
let mut show_session_info = false;
|
||||
let mut show_session_id = false;
|
||||
let mut serve_address = None::<String>;
|
||||
let mut static_path = None::<String>;
|
||||
let mut password = None::<String>;
|
||||
|
|
@ -38,9 +40,16 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
p if p.is_long("list-sessions") => {
|
||||
let control_path: &Path = &control_path;
|
||||
let sessions = sessions::list_sessions(control_path)?;
|
||||
println!("{}", serde_json::to_string(&sessions)?);
|
||||
println!("{}", serde_json::to_string_pretty(&sessions)?);
|
||||
return Ok(());
|
||||
}
|
||||
p if p.is_long("show-session-info") => {
|
||||
show_session_info = true;
|
||||
}
|
||||
p if p.is_long("show-session-id") => {
|
||||
show_session_id = true;
|
||||
show_session_info = true;
|
||||
}
|
||||
p if p.is_long("session-name") => {
|
||||
session_name = Some(parser.value()?);
|
||||
}
|
||||
|
|
@ -93,6 +102,10 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
println!(" --control-path <path> Where the control folder is located");
|
||||
println!(" --session-name <name> Names the session when creating");
|
||||
println!(" --list-sessions List all sessions");
|
||||
println!(" --find-session Find session for current process");
|
||||
println!(
|
||||
" --print-id Print session ID only (implies --find-session)"
|
||||
);
|
||||
println!(" --session <I> Operate on this session");
|
||||
println!(" --send-key <key> Send key input to session");
|
||||
println!(" Keys: arrow_up, arrow_down, arrow_left, arrow_right, escape, enter, ctrl_enter, shift_enter");
|
||||
|
|
@ -117,6 +130,19 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
}
|
||||
}
|
||||
|
||||
// show session info
|
||||
if show_session_info || show_session_id {
|
||||
let control_path: &Path = &control_path;
|
||||
if let Some(entry) = sessions::find_current_session(control_path)? {
|
||||
if show_session_id {
|
||||
println!("{}", entry.session_id);
|
||||
} else {
|
||||
println!("{}", serde_json::to_string_pretty(&entry)?);
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Handle send-key command
|
||||
if let Some(key) = send_key {
|
||||
if let Some(sid) = &session_id {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
|||
|
||||
use crate::tty_spawn::DEFAULT_TERM;
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone)]
|
||||
pub struct SessionInfo {
|
||||
pub cmdline: Vec<String>,
|
||||
pub name: String,
|
||||
|
|
@ -24,7 +24,7 @@ fn get_default_term() -> String {
|
|||
DEFAULT_TERM.to_string()
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct SessionListEntry {
|
||||
#[serde(flatten)]
|
||||
pub session_info: SessionInfo,
|
||||
|
|
@ -35,6 +35,13 @@ pub struct SessionListEntry {
|
|||
pub notification_stream: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct SessionEntryWithId {
|
||||
pub session_id: String,
|
||||
#[serde(flatten)]
|
||||
pub entry: SessionListEntry,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct AsciinemaHeader {
|
||||
pub version: u32,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use std::process::Command;
|
|||
use std::time::Duration;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::protocol::{SessionInfo, SessionListEntry};
|
||||
use crate::protocol::{SessionEntryWithId, SessionInfo, SessionListEntry};
|
||||
use crate::tty_spawn::TtySpawn;
|
||||
|
||||
pub fn list_sessions(
|
||||
|
|
@ -82,6 +82,65 @@ pub fn list_sessions(
|
|||
Ok(sessions)
|
||||
}
|
||||
|
||||
pub fn find_current_session(
|
||||
control_path: &Path,
|
||||
) -> Result<Option<SessionEntryWithId>, anyhow::Error> {
|
||||
let sessions = list_sessions(control_path)?;
|
||||
|
||||
// Get current process PID
|
||||
let current_pid = std::process::id();
|
||||
|
||||
// Check each session to see if current process or any parent is part of it
|
||||
for (session_id, session_entry) in sessions {
|
||||
if let Some(session_pid) = session_entry.session_info.pid {
|
||||
// Check if this session PID is in our process ancestry
|
||||
if is_process_descendant_of(current_pid, session_pid) {
|
||||
return Ok(Some(SessionEntryWithId {
|
||||
session_id,
|
||||
entry: session_entry,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn is_process_descendant_of(mut current_pid: u32, target_pid: u32) -> bool {
|
||||
// Check if current process is the target or a descendant of target
|
||||
while current_pid > 1 {
|
||||
if current_pid == target_pid {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get parent PID
|
||||
match get_parent_pid(current_pid) {
|
||||
Some(parent_pid) => current_pid = parent_pid,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn get_parent_pid(pid: u32) -> Option<u32> {
|
||||
// Use ps command to get parent PID
|
||||
let output = Command::new("ps")
|
||||
.arg("-p")
|
||||
.arg(pid.to_string())
|
||||
.arg("-o")
|
||||
.arg("ppid=")
|
||||
.output()
|
||||
.ok()?;
|
||||
|
||||
if output.status.success() {
|
||||
let ppid_str = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
ppid_str.parse::<u32>().ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_key_to_session(
|
||||
control_path: &Path,
|
||||
session_id: &str,
|
||||
|
|
|
|||
Loading…
Reference in a new issue