| 900 | ); |
| 901 | } |
| 902 | |
| 903 | if (!size) { |
| 904 | return errorResponse('INVALID_REQUEST', 'PTY size is required', 400); |
| 905 | } |
| 906 | |
| 907 | try { |
| 908 | const pty = await deps.kiloClient.resizePty(ptyId, size); |
| 909 | logToFile(`pty/resize: ptyId=${ptyId} cols=${size.cols} rows=${size.rows}`); |
| 910 | return jsonResponse(pty); |
| 911 | } catch (error) { |
| 912 | const msg = error instanceof Error ? error.message : String(error); |
| 913 | logToFile(`pty/resize: failed ptyId=${ptyId}: ${msg}`); |
| 914 | return errorResponse('PTY_ERROR', `Failed to resize PTY: ${msg}`, 500); |
| 915 | } |
| 916 | }; |
| 917 | } |
| 918 | |
| 919 | function createPtyDeleteHandler(deps: ServerDependencies, ptyId: string) { |
| 920 | return async (_req: Request): Promise<Response> => { |
| 921 | try { |
| 922 | const success = await deps.kiloClient.deletePty(ptyId); |
| 923 | logToFile(`pty/delete: ptyId=${ptyId}`); |
| 924 | return jsonResponse({ success }); |
| 925 | } catch (error) { |
| 926 | const msg = error instanceof Error ? error.message : String(error); |
| 927 | logToFile(`pty/delete: failed ptyId=${ptyId}: ${msg}`); |
| 928 | return errorResponse('PTY_ERROR', `Failed to delete PTY: ${msg}`, 500); |
| 929 | } |
| 930 | }; |
| 931 | } |
| 932 | |
| 933 | function buildPtyUpstreamUrl( |
| 934 | config: ServerConfig, |
| 935 | deps: ServerDependencies, |
| 936 | ptyId: string |
| 937 | ): string { |
| 938 | const upstream = new URL(`/pty/${encodeURIComponent(ptyId)}/connect`, deps.kiloClient.serverUrl); |
| 939 | upstream.protocol = upstream.protocol === 'https:' ? 'wss:' : 'ws:'; |
| 940 | upstream.searchParams.set('directory', config.workspacePath); |
| 941 | return upstream.toString(); |
| 942 | } |
| 943 | |
| 944 | type WrapperWebSocketData = { |
| 945 | ptyId?: string; |
| 946 | }; |
| 947 | |
| 948 | type PtyClientClose = { |
| 949 | code: number; |
| 950 | reason: string; |
| 951 | }; |
| 952 | |
| 953 | function isForwardableCloseCode(code: number): boolean { |
| 954 | return ( |
| 955 | Number.isInteger(code) && code >= 1000 && code <= 4999 && ![1005, 1006, 1015].includes(code) |
| 956 | ); |
| 957 | } |
| 958 | |
| 959 | export function resolvePtyClientClose(event: { code: number; reason: string }): PtyClientClose { |