import type { Writable } from 'node:stream'; import { encode } from 'cborg'; import { WSContext } from 'hono/ws'; import { ChannelType } from './encoder'; export interface Command { op: string; payload: unknown; } interface SSHConnectCommand extends Command { op: 'ssh_conn'; payload: { sessionId: string; username: string; hostname: string; port: number; }; } interface SSHCloseCommand extends Command { op: 'ssh_term'; payload: { sessionId: string; }; } type AgentCommand = SSHConnectCommand | SSHCloseCommand; export async function dispatchCommand( dispatcher: Writable, command: AgentCommand, ) { return new Promise((resolve, reject) => { const encodedCommand = Buffer.concat([encode(command), Buffer.from('\n')]); dispatcher.write(encodedCommand, (err) => { if (err) { reject(err); } else { resolve(); } }); }); } export interface SSHConnectData extends Command { op: 'ssh_conn_successful'; payload: { sessionId: string; }; } export interface SSHConnectFailedData extends Command { op: 'ssh_conn_failed'; payload: { reason: string; }; } export interface SSHFrameData extends Command { op: 'ssh_frame'; payload: { channel: ChannelType; frame: Buffer; }; } type WebData = SSHConnectData | SSHConnectFailedData | SSHFrameData; export function dispatchWeb(dispatcher: WSContext, data: WebData) { return dispatcher.send(encode(data)); }