diff --git a/bin/web/views/index.ejs b/bin/web/views/index.ejs index b26f911..94803c5 100644 --- a/bin/web/views/index.ejs +++ b/bin/web/views/index.ejs @@ -170,10 +170,11 @@ n_predict: 200, top_k: 40, top_p: 0.9, - temp: 0.1, + temp: 0.8, repeat_last_n: 64, repeat_penalty: 1.3, debug: false, + html: true, models: [] } const socket = io(); @@ -305,7 +306,7 @@ ${fields} const say = (msg, id) => { let item = document.createElement('li'); if (id) item.setAttribute("data-id", id) - item.textContent = msg; + item.innerHTML = msg; messages.prepend(item); } socket.emit('request', { @@ -328,8 +329,8 @@ ${fields} const id = request.id let existing = document.querySelector(`[data-id='${id}']`) if (existing) { - existing.textContent = existing.textContent + response - existing.textContent = existing.textContent.replaceAll(/\r?\n\x1B\[\d+;\d+H./g, ""); + existing.innerHTML = existing.innerHTML + response + //existing.innerHTML = existing.innerHTML.replaceAll(/\r?\n\x1B\[\d+;\d+H./g, ""); //existing.textContent = existing.textContent.replaceAll("\\n", "\n"); } else { say(response, id) diff --git a/index.js b/index.js index e2c8b8c..1de5148 100644 --- a/index.js +++ b/index.js @@ -23,6 +23,17 @@ const TorrentDownloader = require("./torrent") const exists = s => new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e))) const escapeNewLine = (platform, arg) => platform === 'win32' ? arg.replaceAll(/\n/g, "\\n").replaceAll(/\r/g, "\\r") : arg const escapeDoubleQuotes = (platform, arg) => platform === 'win32' ? arg.replaceAll(/"/g, '`"') : arg.replaceAll(/"/g, '\\"') +const stripAnsi = (str) => { + const pattern = [ + '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', + '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))' + ].join('|'); + + const regex = new RegExp(pattern, 'g') + return str.replace(regex, ''); +} + + class Dalai { constructor(home) { //////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -49,7 +60,7 @@ class Dalai { this.torrent = new TorrentDownloader() this.config = { name: 'xterm-color', - cols: 200, + cols: 1000, rows: 30, } this.cores = { @@ -57,6 +68,32 @@ class Dalai { alpaca: new A(this), } } + htmlencode (str) { + let encodedStr = ''; + for (let i = 0; i < str.length; i++) { + let charCode = str.charCodeAt(i); + if (charCode < 128) { + // ASCII characters + switch (str[i]) { + case '<': encodedStr += '<'; break; + case '>': encodedStr += '>'; break; + case '&': encodedStr += '&'; break; + case '"': encodedStr += '"'; break; + case '\'': encodedStr += '''; break; + case '\n': encodedStr += '
'; break; + case '\r': break; // ignore + case '\t': encodedStr += '    '; break; + case '\b': encodedStr += ' '; break; + case '\f': encodedStr += ' '; break; + default: encodedStr += String.fromCharCode(charCode); break; + } + } else { + // Non-ASCII characters + encodedStr += "&#" + charCode + ";"; + } + } + return encodedStr; + } down(url, dest, headers) { return new Promise((resolve, reject) => { const task = path.basename(dest) @@ -203,7 +240,11 @@ class Dalai { await this.exec(`${main_bin_path} ${chunks.join(" ")}`, this.cores[Core].home, (proc, msg) => { if (endpattern.test(msg)) ended = true if (started && !ended) { - cb(msg) + if (req.html) { + cb(this.htmlencode(msg)) + } else { + cb(msg) + } } else if (ended && writeEnd) { cb('\n\n') writeEnd = false @@ -442,7 +483,7 @@ class Dalai { const ptyProcess = pty.spawn(shell, [], config) ptyProcess.onData((data) => { if (cb) { - cb(ptyProcess, data) + cb(ptyProcess, stripAnsi(data)) } else { process.stdout.write(data); } @@ -456,7 +497,12 @@ class Dalai { resolve(false) } }); - ptyProcess.write(`${cmd}\r`) + + if (platform === "win32") { + ptyProcess.write(`[System.Console]::OutputEncoding=[System.Console]::InputEncoding=[System.Text.Encoding]::UTF8; ${cmd}\r`) + } else { + ptyProcess.write(`${cmd}\r`) + } ptyProcess.write("exit\r") } catch (e) { console.log("caught error", e)