mirror of
https://github.com/hotwa/luci-app-openclaw.git
synced 2026-03-31 04:52:33 +00:00
release: v1.0.0 — LuCI 管理界面、一键安装、12+ AI 模型提供商
This commit is contained in:
BIN
root/usr/share/openclaw/ui/images/icon_256.png
Normal file
BIN
root/usr/share/openclaw/ui/images/icon_256.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
BIN
root/usr/share/openclaw/ui/images/icon_64.png
Normal file
BIN
root/usr/share/openclaw/ui/images/icon_64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
280
root/usr/share/openclaw/ui/index.html
Normal file
280
root/usr/share/openclaw/ui/index.html
Normal file
@@ -0,0 +1,280 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<title>一万AI分享 OpenClaw 配置管理</title>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
html,body{width:100%;height:100%;overflow:hidden;background:#1a1b26;font-family:system-ui,-apple-system,sans-serif}
|
||||
#loading{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#7aa2f7;z-index:100;background:#1a1b26;transition:opacity .4s}
|
||||
#loading.hidden{opacity:0;pointer-events:none}
|
||||
#loading .spinner{width:40px;height:40px;border:3px solid #2a2b3d;border-top:3px solid #ff9e64;border-radius:50%;animation:spin .8s linear infinite;margin-bottom:16px}
|
||||
@keyframes spin{to{transform:rotate(360deg)}}
|
||||
#loading h2{font-size:18px;font-weight:500;margin-bottom:8px}
|
||||
#loading p{font-size:13px;color:#565f89}
|
||||
#loading .debug{font-size:11px;color:#3b3d57;margin-top:12px;max-width:90%;word-break:break-all;text-align:center}
|
||||
#terminal-container{width:100%;height:calc(100% - 36px);position:absolute;top:36px;left:0;right:0;bottom:0;padding:4px;overflow:hidden}
|
||||
.xterm{height:100%!important}
|
||||
.xterm-viewport::-webkit-scrollbar{width:8px}
|
||||
.xterm-viewport::-webkit-scrollbar-thumb{background:#2a2b3d;border-radius:4px}
|
||||
.xterm-viewport::-webkit-scrollbar-thumb:hover{background:#3b3d57}
|
||||
#topbar{position:fixed;top:0;left:0;right:0;height:36px;background:#16161e;border-bottom:1px solid #2a2b3d;display:flex;align-items:center;padding:0 12px;z-index:50;gap:8px}
|
||||
#topbar .logo{font-size:14px;color:#ff9e64;font-weight:600}
|
||||
#topbar .status{font-size:11px;padding:2px 8px;border-radius:10px;background:#2a2b3d}
|
||||
#topbar .status.connected{color:#9ece6a}
|
||||
#topbar .status.disconnected{color:#f7768e}
|
||||
#topbar .btn{font-size:12px;color:#7aa2f7;background:none;border:1px solid #3b3d57;border-radius:4px;padding:3px 10px;cursor:pointer;margin-left:auto}
|
||||
#topbar .btn:hover{background:#2a2b3d}
|
||||
#reconnect-overlay{display:none;position:absolute;inset:0;background:rgba(26,27,38,.9);z-index:80;flex-direction:column;align-items:center;justify-content:center;color:#c0caf5}
|
||||
#reconnect-overlay.show{display:flex}
|
||||
#reconnect-overlay button{margin-top:16px;padding:8px 24px;background:#ff9e64;color:#1a1b26;border:none;border-radius:6px;font-size:14px;cursor:pointer;font-weight:600}
|
||||
#reconnect-overlay button:hover{background:#e0884a}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="topbar">
|
||||
<span class="logo">🦞 一万AI分享 OpenClaw 配置管理</span>
|
||||
<span id="status" class="status disconnected">● 连接中...</span>
|
||||
<button class="btn" onclick="location.reload()" title="重新启动配置脚本">🔄 重启</button>
|
||||
</div>
|
||||
|
||||
<div id="loading">
|
||||
<div class="spinner"></div>
|
||||
<h2>🦞 一万AI分享 OpenClaw 配置管理工具</h2>
|
||||
<p id="loading-msg">正在连接终端...</p>
|
||||
<div id="loading-debug" class="debug"></div>
|
||||
</div>
|
||||
|
||||
<div id="terminal-container"></div>
|
||||
|
||||
<div id="reconnect-overlay">
|
||||
<p style="font-size:16px;margin-bottom:4px">⚡ 连接已断开</p>
|
||||
<p style="font-size:13px;color:#565f89">配置脚本已退出或连接中断</p>
|
||||
<button onclick="location.reload()">🔄 重新启动</button>
|
||||
</div>
|
||||
|
||||
<link rel="stylesheet" href="/lib/xterm.min.css">
|
||||
<script src="/lib/xterm.min.js"></script>
|
||||
<script src="/lib/addon-fit.min.js"></script>
|
||||
<script src="/lib/addon-web-links.min.js"></script>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const statusEl = document.getElementById('status');
|
||||
const loadingEl = document.getElementById('loading');
|
||||
const reconnectEl = document.getElementById('reconnect-overlay');
|
||||
const containerEl = document.getElementById('terminal-container');
|
||||
const loadingMsg = document.getElementById('loading-msg');
|
||||
const loadingDebug = document.getElementById('loading-debug');
|
||||
|
||||
// ── 创建终端 ──
|
||||
const term = new window.Terminal({
|
||||
cursorBlink: true,
|
||||
cursorStyle: 'bar',
|
||||
fontSize: 15,
|
||||
fontFamily: '"Cascadia Code", "Fira Code", "JetBrains Mono", "Source Code Pro", Menlo, Monaco, "Courier New", monospace',
|
||||
lineHeight: 1.2,
|
||||
scrollback: 5000,
|
||||
allowProposedApi: true,
|
||||
theme: {
|
||||
background: '#1a1b26',
|
||||
foreground: '#c0caf5',
|
||||
cursor: '#ff9e64',
|
||||
cursorAccent: '#1a1b26',
|
||||
selectionBackground: '#33467c',
|
||||
selectionForeground: '#c0caf5',
|
||||
black: '#15161e',
|
||||
red: '#f7768e',
|
||||
green: '#9ece6a',
|
||||
yellow: '#e0af68',
|
||||
blue: '#7aa2f7',
|
||||
magenta: '#bb9af7',
|
||||
cyan: '#7dcfff',
|
||||
white: '#a9b1d6',
|
||||
brightBlack: '#414868',
|
||||
brightRed: '#f7768e',
|
||||
brightGreen: '#9ece6a',
|
||||
brightYellow: '#e0af68',
|
||||
brightBlue: '#7aa2f7',
|
||||
brightMagenta: '#bb9af7',
|
||||
brightCyan: '#7dcfff',
|
||||
brightWhite: '#c0caf5',
|
||||
}
|
||||
});
|
||||
|
||||
const fitAddon = new window.FitAddon.FitAddon();
|
||||
term.loadAddon(fitAddon);
|
||||
|
||||
try {
|
||||
const webLinksAddon = new window.WebLinksAddon.WebLinksAddon();
|
||||
term.loadAddon(webLinksAddon);
|
||||
} catch(e) { /* optional */ }
|
||||
|
||||
term.open(containerEl);
|
||||
|
||||
function doFit() {
|
||||
try { fitAddon.fit(); } catch(e) { /* ignore */ }
|
||||
try { term.scrollToBottom(); } catch(e) { /* ignore */ }
|
||||
}
|
||||
doFit();
|
||||
window.addEventListener('resize', () => { setTimeout(doFit, 100); });
|
||||
|
||||
// 监听 iframe 容器大小变化 (FnOS 桌面可能调整窗口大小)
|
||||
if (typeof ResizeObserver !== 'undefined') {
|
||||
new ResizeObserver(function() { setTimeout(doFit, 50); }).observe(containerEl);
|
||||
}
|
||||
|
||||
// ── WebSocket 连接 ──
|
||||
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
// 从 URL 参数或 hash 获取 PTY token 用于 WebSocket 认证
|
||||
const urlParams = new URLSearchParams(location.search);
|
||||
const ptyToken = urlParams.get('pty_token') || '';
|
||||
const wsUrl = proto + '//' + location.host + '/ws' + (ptyToken ? '?token=' + encodeURIComponent(ptyToken) : '');
|
||||
let ws = null;
|
||||
let connected = false;
|
||||
let retryCount = 0;
|
||||
const MAX_RETRY = 20;
|
||||
let retryTimer = null;
|
||||
let wasEverConnected = false;
|
||||
|
||||
console.log('[oc-config] protocol:', location.protocol);
|
||||
console.log('[oc-config] host:', location.host, 'port:', location.port);
|
||||
console.log('[oc-config] WebSocket URL:', wsUrl);
|
||||
loadingDebug.textContent = wsUrl;
|
||||
|
||||
function connect() {
|
||||
if (retryTimer) { clearTimeout(retryTimer); retryTimer = null; }
|
||||
if (ws) { try { ws.close(); } catch(e){} ws = null; }
|
||||
|
||||
retryCount++;
|
||||
console.log('[oc-config] Connecting to', wsUrl, '(attempt', retryCount + ')');
|
||||
loadingMsg.textContent = retryCount > 1
|
||||
? '正在重新连接... (第 ' + retryCount + ' 次)'
|
||||
: '正在连接终端...';
|
||||
loadingDebug.textContent = wsUrl;
|
||||
|
||||
// 先做一个 HTTP 预检确认服务器可达
|
||||
fetch('/health').then(function(r) {
|
||||
return r.json();
|
||||
}).then(function(data) {
|
||||
console.log('[oc-config] Health check OK:', JSON.stringify(data));
|
||||
doWebSocket();
|
||||
}).catch(function(err) {
|
||||
console.log('[oc-config] Health check failed:', err.message || err);
|
||||
// 服务器不可达,稍后重试
|
||||
scheduleRetry();
|
||||
});
|
||||
}
|
||||
|
||||
function doWebSocket() {
|
||||
try {
|
||||
ws = new WebSocket(wsUrl);
|
||||
} catch(e) {
|
||||
console.error('[oc-config] WebSocket constructor error:', e);
|
||||
scheduleRetry();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[oc-config] WebSocket created, readyState:', ws.readyState);
|
||||
|
||||
// 连接超时保护: 5秒没连上就重试
|
||||
var connectTimeout = setTimeout(function() {
|
||||
if (ws && ws.readyState !== WebSocket.OPEN) {
|
||||
console.log('[oc-config] Connection timeout, readyState:', ws.readyState);
|
||||
try { ws.close(); } catch(e){}
|
||||
scheduleRetry();
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
ws.onopen = function() {
|
||||
clearTimeout(connectTimeout);
|
||||
connected = true;
|
||||
wasEverConnected = true;
|
||||
retryCount = 0;
|
||||
loadingEl.classList.add('hidden');
|
||||
reconnectEl.classList.remove('show');
|
||||
statusEl.textContent = '● 已连接';
|
||||
statusEl.className = 'status connected';
|
||||
// 连接后重新 fit,确保尺寸正确
|
||||
setTimeout(doFit, 50);
|
||||
term.focus();
|
||||
try {
|
||||
ws.send(JSON.stringify({ type: 'resize', cols: term.cols, rows: term.rows }));
|
||||
} catch(e) {}
|
||||
};
|
||||
|
||||
ws.onmessage = function(ev) {
|
||||
if (typeof ev.data === 'string') {
|
||||
term.write(ev.data, function() { term.scrollToBottom(); });
|
||||
} else if (ev.data instanceof Blob) {
|
||||
ev.data.text().then(function(text) { term.write(text, function() { term.scrollToBottom(); }); });
|
||||
}
|
||||
};
|
||||
|
||||
ws.onclose = function(ev) {
|
||||
clearTimeout(connectTimeout);
|
||||
connected = false;
|
||||
statusEl.textContent = '● 已断开';
|
||||
statusEl.className = 'status disconnected';
|
||||
console.log('[oc-config] WebSocket closed, code:', ev.code, 'reason:', ev.reason);
|
||||
if (wasEverConnected) {
|
||||
// 自动重连,不显示断连覆盖层
|
||||
console.log('[oc-config] Auto-reconnecting in 2s...');
|
||||
statusEl.textContent = '● 重连中...';
|
||||
retryCount = 0;
|
||||
setTimeout(function() {
|
||||
connect();
|
||||
}, 2000);
|
||||
} else {
|
||||
// 从未连接成功过,自动重试
|
||||
scheduleRetry();
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = function(ev) {
|
||||
clearTimeout(connectTimeout);
|
||||
connected = false;
|
||||
console.error('[oc-config] WebSocket error, will retry');
|
||||
// 不要在这里做UI更新, onclose 会紧跟着触发
|
||||
};
|
||||
}
|
||||
|
||||
function scheduleRetry() {
|
||||
if (retryCount >= MAX_RETRY) {
|
||||
loadingMsg.textContent = '连接失败,请检查服务状态';
|
||||
loadingDebug.textContent = '已重试 ' + MAX_RETRY + ' 次。请刷新页面重试。';
|
||||
statusEl.textContent = '● 连接失败';
|
||||
statusEl.className = 'status disconnected';
|
||||
return;
|
||||
}
|
||||
// 逐步增加重试间隔: 1s, 1s, 2s, 2s, 3s, 3s, ...
|
||||
var delay = Math.min(Math.floor(retryCount / 2) + 1, 5) * 1000;
|
||||
loadingMsg.textContent = '等待服务就绪... ' + Math.ceil(delay/1000) + '秒后重试';
|
||||
console.log('[oc-config] Retry in', delay, 'ms');
|
||||
retryTimer = setTimeout(connect, delay);
|
||||
}
|
||||
|
||||
term.onData(function(data) {
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify({ type: 'stdin', data: data }));
|
||||
}
|
||||
});
|
||||
|
||||
term.onResize(function(size) {
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify({ type: 'resize', cols: size.cols, rows: size.rows }));
|
||||
}
|
||||
});
|
||||
|
||||
// 等 DOM 和资源就绪后再连接
|
||||
if (document.readyState === 'complete') {
|
||||
connect();
|
||||
} else {
|
||||
window.addEventListener('load', connect);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
8
root/usr/share/openclaw/ui/lib/addon-fit.min.js
vendored
Normal file
8
root/usr/share/openclaw/ui/lib/addon-fit.min.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Skipped minification because the original files appears to be already minified.
|
||||
* Original file: /npm/@xterm/addon-fit@0.10.0/lib/addon-fit.js
|
||||
*
|
||||
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
||||
*/
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})()));
|
||||
//# sourceMappingURL=addon-fit.js.map
|
||||
8
root/usr/share/openclaw/ui/lib/addon-web-links.min.js
vendored
Normal file
8
root/usr/share/openclaw/ui/lib/addon-web-links.min.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Skipped minification because the original files appears to be already minified.
|
||||
* Original file: /npm/@xterm/addon-web-links@0.11.0/lib/addon-web-links.js
|
||||
*
|
||||
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
||||
*/
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WebLinksAddon=t():e.WebLinksAddon=t()}(self,(()=>(()=>{"use strict";var e={6:(e,t)=>{function n(e){try{const t=new URL(e),n=t.password&&t.username?`${t.protocol}//${t.username}:${t.password}@${t.host}`:t.username?`${t.protocol}//${t.username}@${t.host}`:`${t.protocol}//${t.host}`;return e.toLocaleLowerCase().startsWith(n.toLocaleLowerCase())}catch(e){return!1}}Object.defineProperty(t,"__esModule",{value:!0}),t.LinkComputer=t.WebLinkProvider=void 0,t.WebLinkProvider=class{constructor(e,t,n,o={}){this._terminal=e,this._regex=t,this._handler=n,this._options=o}provideLinks(e,t){const n=o.computeLink(e,this._regex,this._terminal,this._handler);t(this._addCallbacks(n))}_addCallbacks(e){return e.map((e=>(e.leave=this._options.leave,e.hover=(t,n)=>{if(this._options.hover){const{range:o}=e;this._options.hover(t,n,o)}},e)))}};class o{static computeLink(e,t,r,i){const s=new RegExp(t.source,(t.flags||"")+"g"),[a,c]=o._getWindowedLineStrings(e-1,r),l=a.join("");let d;const p=[];for(;d=s.exec(l);){const e=d[0];if(!n(e))continue;const[t,s]=o._mapStrIdx(r,c,0,d.index),[a,l]=o._mapStrIdx(r,t,s,e.length);if(-1===t||-1===s||-1===a||-1===l)continue;const h={start:{x:s+1,y:t+1},end:{x:l,y:a+1}};p.push({range:h,text:e,activate:i})}return p}static _getWindowedLineStrings(e,t){let n,o=e,r=e,i=0,s="";const a=[];if(n=t.buffer.active.getLine(e)){const e=n.translateToString(!0);if(n.isWrapped&&" "!==e[0]){for(i=0;(n=t.buffer.active.getLine(--o))&&i<2048&&(s=n.translateToString(!0),i+=s.length,a.push(s),n.isWrapped&&-1===s.indexOf(" ")););a.reverse()}for(a.push(e),i=0;(n=t.buffer.active.getLine(++r))&&n.isWrapped&&i<2048&&(s=n.translateToString(!0),i+=s.length,a.push(s),-1===s.indexOf(" ")););}return[a,o]}static _mapStrIdx(e,t,n,o){const r=e.buffer.active,i=r.getNullCell();let s=n;for(;o;){const e=r.getLine(t);if(!e)return[-1,-1];for(let n=s;n<e.length;++n){e.getCell(n,i);const s=i.getChars();if(i.getWidth()&&(o-=s.length||1,n===e.length-1&&""===s)){const e=r.getLine(t+1);e&&e.isWrapped&&(e.getCell(0,i),2===i.getWidth()&&(o+=1))}if(o<0)return[t,n]}t++,s=0}return[t,s]}}t.LinkComputer=o}},t={};function n(o){var r=t[o];if(void 0!==r)return r.exports;var i=t[o]={exports:{}};return e[o](i,i.exports,n),i.exports}var o={};return(()=>{var e=o;Object.defineProperty(e,"__esModule",{value:!0}),e.WebLinksAddon=void 0;const t=n(6),r=/(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;function i(e,t){const n=window.open();if(n){try{n.opener=null}catch{}n.location.href=t}else console.warn("Opening link blocked as opener could not be cleared")}e.WebLinksAddon=class{constructor(e=i,t={}){this._handler=e,this._options=t}activate(e){this._terminal=e;const n=this._options,o=n.urlRegex||r;this._linkProvider=this._terminal.registerLinkProvider(new t.WebLinkProvider(this._terminal,o,this._handler,n))}dispose(){this._linkProvider?.dispose()}}})(),o})()));
|
||||
//# sourceMappingURL=addon-web-links.js.map
|
||||
8
root/usr/share/openclaw/ui/lib/xterm.min.css
vendored
Normal file
8
root/usr/share/openclaw/ui/lib/xterm.min.css
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Minified by jsDelivr using clean-css v5.3.3.
|
||||
* Original file: /npm/@xterm/xterm@5.5.0/css/xterm.css
|
||||
*
|
||||
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
||||
*/
|
||||
.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:0}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm .xterm-cursor-pointer,.xterm.xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}
|
||||
/*# sourceMappingURL=/sm/97377c0c258e109358121823f5790146c714989366481f90e554c42277efb500.map */
|
||||
8
root/usr/share/openclaw/ui/lib/xterm.min.js
vendored
Normal file
8
root/usr/share/openclaw/ui/lib/xterm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user