import type { PluginApiClient } from "@termix/plugin-sdk/frontend"; let client: PluginApiClient | null = null; /** Set from activate with app.api, cleared on deactivate. */ export function setTmuxMonitorApi(api: PluginApiClient | null): void { client = api; } function api(): PluginApiClient { if (!client) throw new Error("The Tmux Monitor plugin is not active"); return client; } export interface TmuxPane { id: string; index: number; pid: number; active: boolean; width: number; height: number; command: string; path: string; title: string; } export interface TmuxWindow { index: number; name: string; active: boolean; panes: TmuxPane[]; } export interface TmuxSessionOverview { name: string; created: number; lastActivity: number; attachedClients: number; windows: TmuxWindow[]; tags: string[]; } export interface TmuxOverview { available: boolean; sessions: TmuxSessionOverview[]; } export interface TmuxSearchMatch { paneId: string; sessionName: string; windowIndex: number; line: number; text: string; } export interface TmuxPaneMetrics { paneId: string; sessionName: string; pid: number; processCount: number; cpuPercent: number; memRssKb: number; gpuMemMb: number; topCommand: string | null; } export async function getTmuxOverview(hostId: number): Promise { const response = await api().get(`/${hostId}/overview`); return response.data; } /** Select a pane's window+pane on the server so the attached terminal * (and any other attached client) switches to it. */ export async function focusTmuxPane( hostId: number, paneId: string, ): Promise { await api().post(`/${hostId}/focus`, { paneId }); } /** Create a new detached session on the host. Starts the tmux server if * none is running yet. */ export async function createTmuxSession( hostId: number, name: string, ): Promise { await api().post(`/${hostId}/sessions`, { name }); } /** Create a new window in an existing session. */ export async function createTmuxWindow( hostId: number, sessionName: string, ): Promise { await api().post(`/${hostId}/windows`, { sessionName }); } /** Rename a session. Saved tags follow the session to its new name. */ export async function renameTmuxSession( hostId: number, sessionName: string, newName: string, ): Promise { await api().post(`/${hostId}/rename`, { sessionName, newName }); } /** Kill a session (terminates all of its windows and processes). */ export async function killTmuxSession( hostId: number, sessionName: string, ): Promise { await api().post(`/${hostId}/kill`, { sessionName }); } /** Kill a window and every pane in it. */ export async function killTmuxWindow( hostId: number, sessionName: string, windowIndex: number, ): Promise { await api().post(`/${hostId}/kill-window`, { sessionName, windowIndex }); } /** Kill a single pane (last pane of a window closes the window). */ export async function killTmuxPane( hostId: number, paneId: string, ): Promise { await api().post(`/${hostId}/kill-pane`, { paneId }); } /** Split the window containing a pane: "h" adds a pane to the right, * "v" below (tmux -h/-v semantics). */ export async function splitTmuxPane( hostId: number, paneId: string, direction: "h" | "v", ): Promise { await api().post(`/${hostId}/split`, { paneId, direction }); } export interface TmuxSearchResult { matches: TmuxSearchMatch[]; /** True when a search limit was hit and the results are partial. */ truncated: boolean; searchedLines: number; maxPanes: number; } export async function searchTmux( hostId: number, query: string, ): Promise { const response = await api().get>( `/${hostId}/search`, { params: { q: query } }, ); return { matches: response.data.matches ?? [], truncated: response.data.truncated ?? false, searchedLines: response.data.searchedLines ?? 0, maxPanes: response.data.maxPanes ?? 0, }; } export async function getTmuxMetrics( hostId: number, ): Promise { const response = await api().get<{ panes?: TmuxPaneMetrics[] }>( `/${hostId}/metrics`, ); return response.data.panes ?? []; } export async function setTmuxSessionTags( hostId: number, sessionName: string, tags: string[], ): Promise { const response = await api().put<{ tags?: string[] }>(`/${hostId}/tags`, { sessionName, tags, }); return response.data.tags ?? []; }