158 lines
4.5 KiB
Python
Raw Normal View History

2025-11-04 07:52:36 +01:00
import subprocess
import threading
import time
from pr.multiplexer import create_multiplexer, get_multiplexer, close_multiplexer, get_all_multiplexer_states
def start_interactive_session(command, session_name=None, process_type='generic'):
"""
Start an interactive session in a dedicated multiplexer.
Args:
command: The command to run (list or string)
session_name: Optional name for the session
process_type: Type of process (ssh, vim, apt, etc.)
Returns:
session_name: The name of the created session
"""
name, mux = create_multiplexer(session_name)
mux.update_metadata('process_type', process_type)
# Start the process
if isinstance(command, str):
command = command.split()
try:
process = subprocess.Popen(
command,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1
)
mux.process = process
mux.update_metadata('pid', process.pid)
# Set process type and handler
detected_type = detect_process_type(command)
mux.set_process_type(detected_type)
# Start output readers
stdout_thread = threading.Thread(target=_read_output, args=(process.stdout, mux.write_stdout), daemon=True)
stderr_thread = threading.Thread(target=_read_output, args=(process.stderr, mux.write_stderr), daemon=True)
stdout_thread.start()
stderr_thread.start()
mux.stdout_thread = stdout_thread
mux.stderr_thread = stderr_thread
return name
except Exception as e:
close_multiplexer(name)
raise e
def _read_output(stream, write_func):
"""Read from a stream and write to multiplexer buffer."""
try:
for line in iter(stream.readline, ''):
if line:
write_func(line.rstrip('\n'))
except Exception as e:
print(f"Error reading output: {e}")
def send_input_to_session(session_name, input_data):
"""
Send input to an interactive session.
Args:
session_name: Name of the session
input_data: Input string to send
"""
mux = get_multiplexer(session_name)
if not mux:
raise ValueError(f"Session {session_name} not found")
if not hasattr(mux, 'process') or mux.process.poll() is not None:
raise ValueError(f"Session {session_name} is not active")
try:
mux.process.stdin.write(input_data + '\n')
mux.process.stdin.flush()
except Exception as e:
raise RuntimeError(f"Failed to send input to session {session_name}: {e}")
def read_session_output(session_name, lines=None):
"""
Read output from a session.
Args:
session_name: Name of the session
lines: Number of recent lines to return (None for all)
Returns:
dict: {'stdout': str, 'stderr': str}
"""
mux = get_multiplexer(session_name)
if not mux:
raise ValueError(f"Session {session_name} not found")
output = mux.get_all_output()
if lines is not None:
# Return last N lines
stdout_lines = output['stdout'].split('\n')[-lines:] if output['stdout'] else []
stderr_lines = output['stderr'].split('\n')[-lines:] if output['stderr'] else []
output = {
'stdout': '\n'.join(stdout_lines),
'stderr': '\n'.join(stderr_lines)
}
return output
def list_active_sessions():
"""
List all active interactive sessions.
Returns:
dict: Session states
"""
return get_all_multiplexer_states()
def get_session_status(session_name):
"""
Get detailed status of a session.
Args:
session_name: Name of the session
Returns:
dict: Session metadata and status
"""
mux = get_multiplexer(session_name)
if not mux:
return None
status = mux.get_metadata()
status['is_active'] = hasattr(mux, 'process') and mux.process.poll() is None
if status['is_active']:
status['pid'] = mux.process.pid
status['output_summary'] = {
'stdout_lines': len(mux.stdout_buffer),
'stderr_lines': len(mux.stderr_buffer)
}
return status
def close_interactive_session(session_name):
"""
Close an interactive session.
"""
try:
mux = get_multiplexer(session_name)
if mux:
mux.process.kill()
close_multiplexer(session_name)
return {"status": "success"}
except Exception as e:
return {"status": "error", "error": str(e)}