commit c1c3151a9f2689b44e4006a3266988de3b3602c3 Author: 10000ge10000 <10000ge10000@users.noreply.github.com> Date: Mon Mar 2 16:23:52 2026 +0800 release: v1.0.0 — LuCI 管理界面、一键安装、12+ AI 模型提供商 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f0c7666 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,114 @@ +name: Build & Release + +on: + workflow_dispatch: + inputs: + version: + description: '版本号 (留空自动生成,格式: 1.0.0)' + required: false + default: '' + create_release: + description: '是否创建 Release' + required: false + type: boolean + default: true + +jobs: + build: + name: Build packages + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Determine version + id: version + run: | + INPUT_VER="${{ github.event.inputs.version }}" + if [ -n "$INPUT_VER" ]; then + VER="$INPUT_VER" + elif [ -f VERSION ]; then + VER="$(cat VERSION | tr -d '[:space:]')" + else + VER="$(date -u +%Y.%m.%d)" + fi + echo "version=$VER" >> "$GITHUB_OUTPUT" + echo "tag=v$VER" >> "$GITHUB_OUTPUT" + echo "Version: $VER" + + - name: Inject version + run: | + VER="${{ steps.version.outputs.version }}" + echo "$VER" > VERSION + # 同步到 Makefile + sed -i "s/^PKG_VERSION:=.*/PKG_VERSION:=$VER/" Makefile + + - name: Build .run installer + run: | + chmod +x scripts/build_run.sh + sh scripts/build_run.sh dist + + - name: Build .ipk package + run: | + chmod +x scripts/build_ipk.sh + sh scripts/build_ipk.sh dist + + - name: List outputs + run: ls -lh dist/ + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: luci-app-openclaw-${{ steps.version.outputs.version }} + path: dist/* + + - name: Create Release + if: ${{ github.event.inputs.create_release == 'true' }} + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.version.outputs.tag }} + name: luci-app-openclaw ${{ steps.version.outputs.tag }} + files: dist/* + draft: false + prerelease: false + body: | + ## luci-app-openclaw ${{ steps.version.outputs.tag }} + + OpenClaw AI 网关的 OpenWrt LuCI 管理插件。 + + ### 下载说明 + + | 文件 | 说明 | + |------|------| + | `luci-app-openclaw_*.run` | 自解压安装包,适用于已运行的 OpenWrt / iStoreOS 系统 | + | `luci-app-openclaw_*.ipk` | 标准 opkg 安装包 | + + ### 安装方法 + + **方式一:.run 安装包(推荐)** + ```bash + # 上传到路由器后执行 + sh luci-app-openclaw_${{ steps.version.outputs.version }}.run + ``` + + **方式二:.ipk 安装** + ```bash + opkg install luci-app-openclaw_${{ steps.version.outputs.version }}-1_all.ipk + ``` + + ### 安装后使用 + + 1. 打开 LuCI → 服务 → OpenClaw + 2. 点击「安装运行环境」,等待安装完成后服务会自动启动 + 3. 进入「Web 控制台」添加 AI 模型的 API Key 即可使用 + + ### 兼容性 + + - 系统:OpenWrt / iStoreOS / ImmortalWrt / KWRT 23.05+ + - 架构:x86_64、aarch64 + - C 库:glibc、musl(自动识别) + + --- + [使用文档](https://github.com/10000ge10000/luci-app-openclaw#readme) · [问题反馈](https://github.com/10000ge10000/luci-app-openclaw/issues) · [B站](https://space.bilibili.com/59438380) · [博客](https://blog.910501.xyz/) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b8324b --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# Node +node_modules/ +*.tgz + +# Build artifacts +dist/ +*.ipk +*.run + +# OS +.DS_Store +Thumbs.db + +# Editor +.vscode/ +*.swp +*.swo +*~ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a038523 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,39 @@ +# Changelog + +本项目所有重大变更都将记录在此文件中。 + +格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/)。 + +## [1.0.0] - 2026-03-02 + +### 新增 +- LuCI 管理界面:基本设置、配置管理(Web 终端)、Web 控制台 +- 一键安装 Node.js + OpenClaw 运行环境 +- 支持 x86_64 和 aarch64 架构,glibc / musl 自动检测 +- 支持 12+ AI 模型提供商配置向导 +- 支持 Telegram / Discord / 飞书 / Slack 消息渠道 +- `.run` 自解压包和 `.ipk` 安装包两种分发方式 +- OpenWrt SDK feeds 集成支持 +- GitHub Actions 自动构建与发布 + +### 安全 +- WebSocket PTY 服务添加 token 认证 +- WebSocket 最大并发会话限制(默认 5) +- PTY 服务默认绑定 127.0.0.1,不对外暴露 +- Token 不再嵌入 HTML 源码,改为 AJAX 动态获取 +- sync_uci_to_json 通过环境变量传递 token,避免 ps 泄露 +- 所有渠道 Token 输入统一 sanitize_input 清洗 + +### 修复 +- Telegram Bot Token 粘贴时被 bracketed paste 转义序列污染 +- Web PTY 终端粘贴包含 ANSI 转义序列问题 +- 恢复出厂配置流程异常退出 +- Gemini CLI OAuth 登录在 OpenWrt 上失败 +- init.d status_service() 在无 netstat 的系统上报错 +- Makefile 损坏导致 OpenWrt SDK 编译失败 + +### 改进 +- 所有 AI 提供商模型列表更新到最新版本 +- UID/GID 动态分配,避免与已有系统用户冲突 +- 版本号统一由 VERSION 文件管理 +- README.md 完善安装说明、FAQ 和项目结构 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f11cd79 --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + +Copyright (c) 2025-2026 10000ge10000 +Project: luci-app-openclaw — OpenClaw AI Gateway LuCI Plugin for OpenWrt + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +The full text of the GNU General Public License version 3 is available at: +https://www.gnu.org/licenses/gpl-3.0.html +SOFTWARE. + +This project integrates with OpenClaw (https://github.com/nicepkg/openclaw), +which is licensed under its own terms. Node.js runtime downloaded during setup +is subject to the Node.js license (https://github.com/nodejs/node/blob/main/LICENSE). diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0450e7d --- /dev/null +++ b/Makefile @@ -0,0 +1,92 @@ +# luci-app-openclaw — OpenWrt package Makefile +# 兼容两种集成方式: +# 1. 作为 feeds 源: echo "src-git openclaw ..." >> feeds.conf.default +# 2. 直接放入 package/ 目录: git clone ... package/luci-app-openclaw + +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-openclaw +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=10000ge10000 <10000ge10000@users.noreply.github.com> +PKG_LICENSE:=GPL-3.0 + +LUCI_TITLE:=OpenClaw AI 网关 LuCI 管理插件 +LUCI_DEPENDS:=+luci-compat +luci-base +curl +openssl-util +LUCI_PKGARCH:=all + +# 优先使用 luci.mk (feeds 模式), 不可用时回退 package.mk +ifeq ($(wildcard $(TOPDIR)/feeds/luci/luci.mk),) + + include $(INCLUDE_DIR)/package.mk + + define Package/$(PKG_NAME) + SECTION:=luci + CATEGORY:=LuCI + SUBMENU:=3. Applications + TITLE:=$(LUCI_TITLE) + DEPENDS:=$(LUCI_DEPENDS) + PKGARCH:=all + endef + + define Package/$(PKG_NAME)/description + OpenClaw AI Gateway 的 LuCI 管理插件。 + 支持 12+ AI 模型提供商和 Telegram/Discord 等多种消息渠道。 + endef + +else + + include $(TOPDIR)/feeds/luci/luci.mk + +endif + +define Package/$(PKG_NAME)/conffiles +/etc/config/openclaw +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./root/etc/config/openclaw $(1)/etc/config/openclaw + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_BIN) ./root/etc/uci-defaults/99-openclaw $(1)/etc/uci-defaults/99-openclaw + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./root/etc/init.d/openclaw $(1)/etc/init.d/openclaw + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) ./root/usr/bin/openclaw-env $(1)/usr/bin/openclaw-env + $(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller + $(INSTALL_DATA) ./luasrc/controller/openclaw.lua $(1)/usr/lib/lua/luci/controller/openclaw.lua + $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/openclaw + $(INSTALL_DATA) ./luasrc/model/cbi/openclaw/basic.lua $(1)/usr/lib/lua/luci/model/cbi/openclaw/basic.lua + $(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/openclaw + $(INSTALL_DATA) ./luasrc/view/openclaw/status.htm $(1)/usr/lib/lua/luci/view/openclaw/status.htm + $(INSTALL_DATA) ./luasrc/view/openclaw/advanced.htm $(1)/usr/lib/lua/luci/view/openclaw/advanced.htm + $(INSTALL_DATA) ./luasrc/view/openclaw/console.htm $(1)/usr/lib/lua/luci/view/openclaw/console.htm + $(INSTALL_DIR) $(1)/usr/share/openclaw + $(INSTALL_BIN) ./root/usr/share/openclaw/oc-config.sh $(1)/usr/share/openclaw/oc-config.sh + $(INSTALL_DATA) ./root/usr/share/openclaw/web-pty.js $(1)/usr/share/openclaw/web-pty.js + $(INSTALL_DIR) $(1)/usr/share/openclaw/ui + $(CP) ./root/usr/share/openclaw/ui/* $(1)/usr/share/openclaw/ui/ + $(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n + if [ -f ./po/zh-cn/openclaw.po ]; then \ + po2lmo ./po/zh-cn/openclaw.po $(1)/usr/lib/lua/luci/i18n/openclaw.zh-cn.lmo 2>/dev/null || true; \ + fi +endef + +define Package/$(PKG_NAME)/postinst +#!/bin/sh +[ -n "$${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/99-openclaw ) && rm -f /etc/uci-defaults/99-openclaw + rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* 2>/dev/null + exit 0 +} +endef + +define Package/$(PKG_NAME)/postrm +#!/bin/sh +[ -n "$${IPKG_INSTROOT}" ] || { + rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* 2>/dev/null +} +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/README.md b/README.md new file mode 100644 index 0000000..b9c5e1d --- /dev/null +++ b/README.md @@ -0,0 +1,155 @@ +# luci-app-openclaw + +[![Bilibili](https://img.shields.io/badge/B%E7%AB%99-59438380-00a1d6?logo=bilibili)](https://space.bilibili.com/59438380) +[![Blog](https://img.shields.io/badge/Blog-910501.xyz-orange)](https://blog.910501.xyz/) +[![Build & Release](https://github.com/10000ge10000/luci-app-openclaw/actions/workflows/build.yml/badge.svg)](https://github.com/10000ge10000/luci-app-openclaw/actions/workflows/build.yml) +[![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](LICENSE) + +[OpenClaw](https://github.com/nicepkg/openclaw) AI 网关的 OpenWrt LuCI 管理插件。 + +在路由器上运行 OpenClaw,通过 LuCI 管理界面完成安装、配置和服务管理。 + +**系统要求** + +| 项目 | 要求 | +|------|------| +| 架构 | x86_64 或 aarch64 | +| C 库 | glibc 或 musl(自动检测) | +| 依赖 | luci-compat, luci-base, curl, openssl-util | +| 存储 | 1.5GB 以上可用空间 | +| 内存 | 推荐 2GB 及以上 | + +## 📦 安装 + +### 方式一:.run 自解压包(推荐) + +无需 SDK,适用于已安装好的系统。 + +```bash +wget https://github.com/10000ge10000/luci-app-openclaw/releases/latest/download/luci-app-openclaw.run +sh luci-app-openclaw.run +``` + +### 方式二:.ipk 安装 + +```bash +wget https://github.com/10000ge10000/luci-app-openclaw/releases/latest/download/luci-app-openclaw.ipk +opkg install luci-app-openclaw.ipk +``` + +### 方式三:集成到固件编译 + +适用于自行编译固件或使用在线编译平台的用户。 + +```bash +cd /path/to/openwrt + +# 添加 feeds +echo "src-git openclaw https://github.com/10000ge10000/luci-app-openclaw.git" >> feeds.conf.default + +# 更新安装 +./scripts/feeds update -a +./scripts/feeds install -a + +# 选择插件 +make menuconfig +# LuCI → Applications → luci-app-openclaw + +# 编译 +make package/luci-app-openclaw/compile V=s +``` + +使用 OpenWrt SDK 单独编译: + +```bash +git clone https://github.com/10000ge10000/luci-app-openclaw.git package/luci-app-openclaw +make defconfig +make package/luci-app-openclaw/compile V=s +find bin/ -name "luci-app-openclaw*.ipk" +``` + +### 方式四:手动安装 + +```bash +git clone https://github.com/10000ge10000/luci-app-openclaw.git +cd luci-app-openclaw + +cp -r root/* / +mkdir -p /usr/lib/lua/luci/controller /usr/lib/lua/luci/model/cbi/openclaw /usr/lib/lua/luci/view/openclaw +cp luasrc/controller/openclaw.lua /usr/lib/lua/luci/controller/ +cp luasrc/model/cbi/openclaw/*.lua /usr/lib/lua/luci/model/cbi/openclaw/ +cp luasrc/view/openclaw/*.htm /usr/lib/lua/luci/view/openclaw/ + +chmod +x /etc/init.d/openclaw /usr/bin/openclaw-env /usr/share/openclaw/oc-config.sh +sh /etc/uci-defaults/99-openclaw +rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* +``` + +## 🔰 首次使用 + +1. 打开 LuCI → 服务 → OpenClaw,点击「安装运行环境」 +2. 安装完成后服务会自动启动,点击「刷新页面」查看状态 +3. 进入「Web 控制台」添加 AI 模型和 API Key +4. 进入「配置管理」可使用向导配置消息渠道 + +## 📂 目录结构 + +``` +luci-app-openclaw/ +├── Makefile # OpenWrt 包定义 +├── luasrc/ +│ ├── controller/openclaw.lua # LuCI 路由和 API +│ ├── model/cbi/openclaw/basic.lua # 主页面 +│ └── view/openclaw/ +│ ├── status.htm # 状态面板 +│ ├── advanced.htm # 配置管理(终端) +│ └── console.htm # Web 控制台 +├── root/ +│ ├── etc/ +│ │ ├── config/openclaw # UCI 配置 +│ │ ├── init.d/openclaw # 服务脚本 +│ │ └── uci-defaults/99-openclaw # 初始化脚本 +│ └── usr/ +│ ├── bin/openclaw-env # 环境管理工具 +│ └── share/openclaw/ # 配置终端资源 +├── scripts/ +│ ├── build_ipk.sh # 本地 IPK 构建 +│ └── build_run.sh # .run 安装包构建 +└── .github/workflows/build.yml # GitHub Actions +``` + +## ❓ 常见问题 + +**安装后 LuCI 菜单没有出现** + +```bash +rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* +``` + +刷新浏览器即可。 + +**提示缺少依赖 luci-compat** + +```bash +opkg update && opkg install luci-compat +``` + +**Node.js 下载失败** + +网络问题,可指定国内镜像: + +```bash +NODE_MIRROR=https://npmmirror.com/mirrors/node openclaw-env setup +``` + +**是否支持 ARM 路由器** + +支持 aarch64(ARM64)。不支持 32 位 ARM,Node.js 22 没有 32 位预编译包。 + +## 🤝 贡献 + +欢迎提交 Issue 和 Pull Request! + +## 📄 License + +[GPL-3.0](LICENSE) diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.0.0 diff --git a/luasrc/controller/openclaw.lua b/luasrc/controller/openclaw.lua new file mode 100644 index 0000000..efcea54 --- /dev/null +++ b/luasrc/controller/openclaw.lua @@ -0,0 +1,384 @@ +-- luci-app-openclaw — LuCI Controller +module("luci.controller.openclaw", package.seeall) + +-- 公共辅助: 获取 OpenClaw 版本号 +local function get_openclaw_version() + local sys = require "luci.sys" + local ver = sys.exec("[ -x /opt/openclaw/node/bin/node ] && for d in /opt/openclaw/global/lib/node_modules/openclaw /opt/openclaw/global/node_modules/openclaw /opt/openclaw/global/*/node_modules/openclaw; do [ -f \"$d/openclaw.mjs\" ] && /opt/openclaw/node/bin/node \"$d/openclaw.mjs\" --version 2>/dev/null && break; [ -f \"$d/dist/cli.js\" ] && /opt/openclaw/node/bin/node \"$d/dist/cli.js\" --version 2>/dev/null && break; done"):gsub("%s+", "") + return ver +end + +function index() + -- 主入口: 服务 → OpenClaw (🧠 作为菜单图标) + local page = entry({"admin", "services", "openclaw"}, alias("admin", "services", "openclaw", "basic"), _("OpenClaw"), 90) + page.dependent = false + + -- 基本设置 (CBI) + entry({"admin", "services", "openclaw", "basic"}, cbi("openclaw/basic"), _("基本设置"), 10).leaf = true + + -- 配置管理 (View — 嵌入 oc-config Web 终端) + entry({"admin", "services", "openclaw", "advanced"}, template("openclaw/advanced"), _("配置管理"), 20).leaf = true + + -- Web 控制台 (View — 嵌入 OpenClaw Web UI) + entry({"admin", "services", "openclaw", "console"}, template("openclaw/console"), _("Web 控制台"), 30).leaf = true + + -- 状态 API (AJAX 接口, 供前端 XHR 调用) + entry({"admin", "services", "openclaw", "status_api"}, call("action_status"), nil).leaf = true + + -- 服务控制 API + entry({"admin", "services", "openclaw", "service_ctl"}, call("action_service_ctl"), nil).leaf = true + + -- 安装/升级日志 API (轮询) + entry({"admin", "services", "openclaw", "setup_log"}, call("action_setup_log"), nil).leaf = true + + -- 版本检查 API + entry({"admin", "services", "openclaw", "check_update"}, call("action_check_update"), nil).leaf = true + + -- 执行升级 API + entry({"admin", "services", "openclaw", "do_update"}, call("action_do_update"), nil).leaf = true + + -- 升级日志 API (轮询) + entry({"admin", "services", "openclaw", "upgrade_log"}, call("action_upgrade_log"), nil).leaf = true + + -- 卸载运行环境 API + entry({"admin", "services", "openclaw", "uninstall"}, call("action_uninstall"), nil).leaf = true + + -- 获取网关 Token API (仅认证用户可访问) + entry({"admin", "services", "openclaw", "get_token"}, call("action_get_token"), nil).leaf = true +end + +-- ═══════════════════════════════════════════ +-- 状态查询 API: 返回 JSON +-- ═══════════════════════════════════════════ +function action_status() + local http = require "luci.http" + local sys = require "luci.sys" + local uci = require "luci.model.uci".cursor() + + local port = uci:get("openclaw", "main", "port") or "18789" + local pty_port = uci:get("openclaw", "main", "pty_port") or "18793" + local enabled = uci:get("openclaw", "main", "enabled") or "0" + + -- 验证端口值为纯数字,防止命令注入 + if not port:match("^%d+$") then port = "18789" end + if not pty_port:match("^%d+$") then pty_port = "18793" end + + local result = { + enabled = enabled, + port = port, + pty_port = pty_port, + gateway_running = false, + pty_running = false, + pid = "", + memory_kb = 0, + uptime = "", + node_version = "", + openclaw_version = "", + } + + -- 检查 Node.js + local node_bin = "/opt/openclaw/node/bin/node" + local f = io.open(node_bin, "r") + if f then + f:close() + local node_ver = sys.exec(node_bin .. " --version 2>/dev/null"):gsub("%s+", "") + result.node_version = node_ver + end + + -- 检查 OpenClaw 版本 + local oc_ver = get_openclaw_version() + if oc_ver and oc_ver ~= "" then + result.openclaw_version = "v" .. oc_ver + end + + -- 网关端口检查 + local gw_check = sys.exec("netstat -tlnp 2>/dev/null | grep -c ':" .. port .. " ' || echo 0"):gsub("%s+", "") + result.gateway_running = (tonumber(gw_check) or 0) > 0 + + -- PTY 端口检查 + local pty_check = sys.exec("netstat -tlnp 2>/dev/null | grep -c ':" .. pty_port .. " ' || echo 0"):gsub("%s+", "") + result.pty_running = (tonumber(pty_check) or 0) > 0 + + -- PID 和内存 + if result.gateway_running then + local pid = sys.exec("netstat -tlnp 2>/dev/null | grep ':" .. port .. " ' | head -1 | sed 's|.* \\([0-9]*\\)/.*|\\1|'"):gsub("%s+", "") + if pid and pid ~= "" then + result.pid = pid + -- 内存 (VmRSS from /proc) + local rss = sys.exec("awk '/VmRSS/{print $2}' /proc/" .. pid .. "/status 2>/dev/null"):gsub("%s+", "") + result.memory_kb = tonumber(rss) or 0 + -- 运行时间 + local stat_time = sys.exec("stat -c %Y /proc/" .. pid .. " 2>/dev/null"):gsub("%s+", "") + local start_ts = tonumber(stat_time) or 0 + if start_ts > 0 then + local uptime_s = os.time() - start_ts + local hours = math.floor(uptime_s / 3600) + local mins = math.floor((uptime_s % 3600) / 60) + local secs = uptime_s % 60 + if hours > 0 then + result.uptime = string.format("%dh %dm %ds", hours, mins, secs) + elseif mins > 0 then + result.uptime = string.format("%dm %ds", mins, secs) + else + result.uptime = string.format("%ds", secs) + end + end + end + end + + http.prepare_content("application/json") + http.write_json(result) +end + +-- ═══════════════════════════════════════════ +-- 服务控制 API: start/stop/restart/setup +-- ═══════════════════════════════════════════ +function action_service_ctl() + local http = require "luci.http" + local sys = require "luci.sys" + + local action = http.formvalue("action") or "" + + if action == "start" then + sys.exec("/etc/init.d/openclaw start >/dev/null 2>&1 &") + elseif action == "stop" then + sys.exec("/etc/init.d/openclaw stop >/dev/null 2>&1") + elseif action == "restart" then + sys.exec("/etc/init.d/openclaw restart >/dev/null 2>&1 &") + elseif action == "enable" then + sys.exec("/etc/init.d/openclaw enable 2>/dev/null") + elseif action == "disable" then + sys.exec("/etc/init.d/openclaw disable 2>/dev/null") + elseif action == "setup" then + -- 先清理旧日志和状态 + sys.exec("rm -f /tmp/openclaw-setup.log /tmp/openclaw-setup.pid /tmp/openclaw-setup.exit") + -- 获取用户选择的版本 (stable=指定版本, latest=最新版) + local version = http.formvalue("version") or "" + local env_prefix = "" + if version == "stable" then + -- 稳定版: 读取 openclaw-env 中定义的 OC_TESTED_VERSION + local tested_ver = sys.exec("grep '^OC_TESTED_VERSION=' /usr/bin/openclaw-env 2>/dev/null | cut -d'\"' -f2"):gsub("%s+", "") + if tested_ver ~= "" then + env_prefix = "OC_VERSION=" .. tested_ver .. " " + end + elseif version ~= "" and version ~= "latest" then + -- 校验版本号格式 (仅允许数字、点、横线、字母) + if version:match("^[%d%.%-a-zA-Z]+$") then + env_prefix = "OC_VERSION=" .. version .. " " + end + end + -- 后台安装,成功后自动启用并启动服务 + -- 注: openclaw-env 脚本有 set -e,init_openclaw 中的非关键失败不应阻止启动 + sys.exec("( " .. env_prefix .. "/usr/bin/openclaw-env setup > /tmp/openclaw-setup.log 2>&1; RC=$?; echo $RC > /tmp/openclaw-setup.exit; if [ $RC -eq 0 ]; then uci set openclaw.main.enabled=1; uci commit openclaw; /etc/init.d/openclaw enable 2>/dev/null; sleep 1; /etc/init.d/openclaw start >> /tmp/openclaw-setup.log 2>&1; fi ) & echo $! > /tmp/openclaw-setup.pid") + http.prepare_content("application/json") + http.write_json({ status = "ok", message = "安装已启动,请查看安装日志..." }) + return + else + http.prepare_content("application/json") + http.write_json({ status = "error", message = "未知操作: " .. action }) + return + end + + http.prepare_content("application/json") + http.write_json({ status = "ok", action = action }) +end + +-- ═══════════════════════════════════════════ +-- 安装日志轮询 API +-- ═══════════════════════════════════════════ +function action_setup_log() + local http = require "luci.http" + local sys = require "luci.sys" + + -- 读取日志内容 + local log = "" + local f = io.open("/tmp/openclaw-setup.log", "r") + if f then + log = f:read("*a") or "" + f:close() + end + + -- 检查进程是否还在运行 + local running = false + local pid_file = io.open("/tmp/openclaw-setup.pid", "r") + if pid_file then + local pid = pid_file:read("*a"):gsub("%s+", "") + pid_file:close() + if pid ~= "" then + local check = sys.exec("kill -0 " .. pid .. " 2>/dev/null && echo yes || echo no"):gsub("%s+", "") + running = (check == "yes") + end + end + + -- 读取退出码 + local exit_code = -1 + if not running then + local exit_file = io.open("/tmp/openclaw-setup.exit", "r") + if exit_file then + local code = exit_file:read("*a"):gsub("%s+", "") + exit_file:close() + exit_code = tonumber(code) or -1 + end + end + + -- 判断状态 + local state = "idle" + if running then + state = "running" + elseif exit_code == 0 then + state = "success" + elseif exit_code > 0 then + state = "failed" + end + + http.prepare_content("application/json") + http.write_json({ + state = state, + exit_code = exit_code, + log = log + }) +end + +-- ═══════════════════════════════════════════ +-- 版本检查 API +-- ═══════════════════════════════════════════ +function action_check_update() + local http = require "luci.http" + local sys = require "luci.sys" + + -- 当前版本 + local current = get_openclaw_version() + + -- 最新版本 (从 npm registry 查询) + local latest = sys.exec("PATH=/opt/openclaw/node/bin:/opt/openclaw/global/bin:$PATH npm view openclaw version 2>/dev/null"):gsub("%s+", "") + + local has_update = false + if current ~= "" and latest ~= "" and current ~= latest then + has_update = true + end + + http.prepare_content("application/json") + http.write_json({ + status = "ok", + current = current, + latest = latest, + has_update = has_update + }) +end + +-- ═══════════════════════════════════════════ +-- 执行升级 API (后台执行 + 日志轮询) +-- ═══════════════════════════════════════════ +function action_do_update() + local http = require "luci.http" + local sys = require "luci.sys" + + -- 清理旧日志和状态 + sys.exec("rm -f /tmp/openclaw-upgrade.log /tmp/openclaw-upgrade.pid /tmp/openclaw-upgrade.exit") + + -- 后台执行升级,升级完成后自动重启服务 + sys.exec("( /usr/bin/openclaw-env upgrade > /tmp/openclaw-upgrade.log 2>&1; RC=$?; echo $RC > /tmp/openclaw-upgrade.exit; if [ $RC -eq 0 ]; then echo '' >> /tmp/openclaw-upgrade.log; echo '正在重启服务...' >> /tmp/openclaw-upgrade.log; /etc/init.d/openclaw restart >> /tmp/openclaw-upgrade.log 2>&1; echo ' [✓] 服务已重启' >> /tmp/openclaw-upgrade.log; fi ) & echo $! > /tmp/openclaw-upgrade.pid") + + http.prepare_content("application/json") + http.write_json({ + status = "ok", + message = "升级已在后台启动,请查看升级日志..." + }) +end + +-- ═══════════════════════════════════════════ +-- 升级日志轮询 API +-- ═══════════════════════════════════════════ +function action_upgrade_log() + local http = require "luci.http" + local sys = require "luci.sys" + + -- 读取日志内容 + local log = "" + local f = io.open("/tmp/openclaw-upgrade.log", "r") + if f then + log = f:read("*a") or "" + f:close() + end + + -- 检查进程是否还在运行 + local running = false + local pid_file = io.open("/tmp/openclaw-upgrade.pid", "r") + if pid_file then + local pid = pid_file:read("*a"):gsub("%s+", "") + pid_file:close() + if pid ~= "" then + local check = sys.exec("kill -0 " .. pid .. " 2>/dev/null && echo yes || echo no"):gsub("%s+", "") + running = (check == "yes") + end + end + + -- 读取退出码 + local exit_code = -1 + if not running then + local exit_file = io.open("/tmp/openclaw-upgrade.exit", "r") + if exit_file then + local code = exit_file:read("*a"):gsub("%s+", "") + exit_file:close() + exit_code = tonumber(code) or -1 + end + end + + -- 判断状态 + local state = "idle" + if running then + state = "running" + elseif exit_code == 0 then + state = "success" + elseif exit_code > 0 then + state = "failed" + end + + http.prepare_content("application/json") + http.write_json({ + state = state, + exit_code = exit_code, + log = log + }) +end + +-- ═══════════════════════════════════════════ +-- 卸载运行环境 API +-- ═══════════════════════════════════════════ +function action_uninstall() + local http = require "luci.http" + local sys = require "luci.sys" + + -- 停止服务 + sys.exec("/etc/init.d/openclaw stop >/dev/null 2>&1") + -- 禁用开机启动 + sys.exec("/etc/init.d/openclaw disable 2>/dev/null") + -- 设置 UCI enabled=0 + sys.exec("uci set openclaw.main.enabled=0; uci commit openclaw 2>/dev/null") + -- 删除 Node.js + OpenClaw 运行环境 + sys.exec("rm -rf /opt/openclaw") + -- 清理临时文件 + sys.exec("rm -f /tmp/openclaw-setup.* /tmp/openclaw-update.log /var/run/openclaw*.pid") + -- 删除 openclaw 系统用户 + sys.exec("sed -i '/^openclaw:/d' /etc/passwd /etc/shadow /etc/group 2>/dev/null") + + http.prepare_content("application/json") + http.write_json({ + status = "ok", + message = "运行环境已卸载。Node.js、OpenClaw 及相关数据已清理。" + }) +end + +-- ═══════════════════════════════════════════ +-- 获取 Token API +-- 仅通过 LuCI 认证后可调用,避免 Token 嵌入 HTML 源码 +-- 返回网关 Token 和 PTY Token +-- ═══════════════════════════════════════════ +function action_get_token() + local http = require "luci.http" + local uci = require "luci.model.uci".cursor() + local token = uci:get("openclaw", "main", "token") or "" + local pty_token = uci:get("openclaw", "main", "pty_token") or "" + http.prepare_content("application/json") + http.write_json({ token = token, pty_token = pty_token }) +end diff --git a/luasrc/model/cbi/openclaw/basic.lua b/luasrc/model/cbi/openclaw/basic.lua new file mode 100644 index 0000000..e727ab0 --- /dev/null +++ b/luasrc/model/cbi/openclaw/basic.lua @@ -0,0 +1,366 @@ +-- luci-app-openclaw — 基本设置 CBI Model +local sys = require "luci.sys" + +m = Map("openclaw", "OpenClaw AI 网关", + "OpenClaw 是一个 AI 编程代理网关,支持 GitHub Copilot、Claude、GPT、Gemini 等大模型以及 Telegram、Discord 等多种消息渠道。") + +-- 隐藏底部的「保存并应用」「保存」「复位」按钮 (本页无可编辑的 UCI 选项) +m.submit = false +m.reset = false + +-- ═══════════════════════════════════════════ +-- 状态面板 +-- ═══════════════════════════════════════════ +m:section(SimpleSection).template = "openclaw/status" + +-- ═══════════════════════════════════════════ +-- 快捷操作 +-- ═══════════════════════════════════════════ +s3 = m:section(SimpleSection, nil, "快捷操作") +s3.template = "cbi/nullsection" + +act = s3:option(DummyValue, "_actions") +act.rawhtml = true +act.cfgvalue = function(self, section) + local ctl_url = luci.dispatcher.build_url("admin", "services", "openclaw", "service_ctl") + local log_url = luci.dispatcher.build_url("admin", "services", "openclaw", "setup_log") + local check_url = luci.dispatcher.build_url("admin", "services", "openclaw", "check_update") + local update_url = luci.dispatcher.build_url("admin", "services", "openclaw", "do_update") + local upgrade_log_url = luci.dispatcher.build_url("admin", "services", "openclaw", "upgrade_log") + local uninstall_url = luci.dispatcher.build_url("admin", "services", "openclaw", "uninstall") + local html = {} + + -- 按钮区域 + html[#html+1] = '
' + html[#html+1] = '' + html[#html+1] = '' + html[#html+1] = '' + html[#html+1] = '' + html[#html+1] = '' + html[#html+1] = '
' + html[#html+1] = '
' + html[#html+1] = '' + + -- 版本选择对话框 (默认隐藏) + html[#html+1] = '' + + -- 安装日志面板 (默认隐藏) + html[#html+1] = '' + + -- JavaScript + html[#html+1] = '' + return table.concat(html, "\n") +end + +-- ═══════════════════════════════════════════ +-- 使用指南 +-- ═══════════════════════════════════════════ +s4 = m:section(SimpleSection, nil) +s4.template = "cbi/nullsection" +guide = s4:option(DummyValue, "_guide") +guide.rawhtml = true +guide.cfgvalue = function() + local html = {} + html[#html+1] = '
' + html[#html+1] = '📖 使用指南
' + html[#html+1] = '' + html[#html+1] = '① 首次使用请点击 「安装运行环境」,安装完成后服务会自动启动
' + html[#html+1] = '② 进入 「Web 控制台」 配置 AI 模型、消息渠道,直接开始对话
' + html[#html+1] = '③ 进入 「配置管理」 可使用交互式向导进行高级配置
' + html[#html+1] = '
' + html[#html+1] = '有疑问?请关注B站并留言:' + html[#html+1] = '' + html[#html+1] = '🔗 space.bilibili.com/59438380' + html[#html+1] = 'GitHub 项目:' + html[#html+1] = '' + html[#html+1] = '🐙 10000ge10000/luci-app-openclaw
' + return table.concat(html, "\n") +end + +return m diff --git a/luasrc/view/openclaw/advanced.htm b/luasrc/view/openclaw/advanced.htm new file mode 100644 index 0000000..33faf45 --- /dev/null +++ b/luasrc/view/openclaw/advanced.htm @@ -0,0 +1,121 @@ +<%# + luci-app-openclaw — 终端配置页面 (简洁版) +-%> +<%+header%> + +<% +local uci = require "luci.model.uci".cursor() +local pty_port = uci:get("openclaw", "main", "pty_port") or "18793" +%> + + + +
+

⚙️ 终端配置

+

通过内嵌的交互式终端 (oc-config) 进行 OpenClaw 的完整配置管理。支持 AI 模型配置、消息渠道设置、健康检查等。

+
+ +
+ 💡 菜单功能说明: + +
+ +
+
+
+ ⏳ 正在连接配置终端... +
+
+
+ + + +<%+footer%> diff --git a/luasrc/view/openclaw/console.htm b/luasrc/view/openclaw/console.htm new file mode 100644 index 0000000..da796b1 --- /dev/null +++ b/luasrc/view/openclaw/console.htm @@ -0,0 +1,168 @@ +<%# + luci-app-openclaw — Web 控制台页面 + 嵌入 OpenClaw 官方 Web UI,用户可在此配置模型/渠道并直接对话 +-%> +<%+header%> + +<% +local uci = require "luci.model.uci".cursor() +local port = uci:get("openclaw", "main", "port") or "18789" +%> + + + +
+

🖥️ Web 控制台

+

OpenClaw 官方 Web 管理界面 — 在这里可以配置 AI 模型、消息渠道,直接与 AI 进行对话,以及管理所有功能。

+
+ +
+ 网关地址: + - + | + 状态: + 检查中... + +
+ +
+
+
+
+ 正在连接 OpenClaw 控制台... +
+
+
+ + + +<%+footer%> diff --git a/luasrc/view/openclaw/status.htm b/luasrc/view/openclaw/status.htm new file mode 100644 index 0000000..1f9397f --- /dev/null +++ b/luasrc/view/openclaw/status.htm @@ -0,0 +1,138 @@ +<%# + luci-app-openclaw — 运行状态面板 (全面汉化 + 界面优化) +-%> + + + +
+
🦞 OpenClaw 服务状态
+
+ + + + + + + + + +
运行状态加载中...
网关服务-
配置终端-
进程 PID-
内存占用-
运行时间-
Node.js-
OpenClaw-
+
+
+ + diff --git a/po/zh-cn/openclaw.po b/po/zh-cn/openclaw.po new file mode 100644 index 0000000..12aff11 --- /dev/null +++ b/po/zh-cn/openclaw.po @@ -0,0 +1,482 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Language: zh-cn\n" + +# ═══════════════════════════════════════════ +# controller/openclaw.lua — 菜单 & API +# ═══════════════════════════════════════════ + +msgid "OpenClaw" +msgstr "OpenClaw AI 网关" + +msgid "OpenClaw AI Gateway" +msgstr "OpenClaw AI 网关" + +msgid "Basic Settings" +msgstr "基本设置" + +msgid "Model Settings" +msgstr "模型设置" + +msgid "Channel Settings" +msgstr "渠道设置" + +msgid "Advanced" +msgstr "高级配置" + +# ═══════════════════════════════════════════ +# basic.lua — 基本设置页 +# ═══════════════════════════════════════════ + +msgid "OpenClaw is an AI coding agent gateway that supports GitHub Copilot, Claude, GPT, Gemini and various messaging channels." +msgstr "OpenClaw 是一个 AI 编程代理网关,支持 GitHub Copilot、Claude、GPT、Gemini 等大模型以及多种消息渠道。" + +msgid "Enable" +msgstr "启用" + +msgid "Enable OpenClaw AI Gateway" +msgstr "启用 OpenClaw AI 网关" + +msgid "Gateway Port" +msgstr "网关端口" + +msgid "OpenClaw API listening port" +msgstr "OpenClaw API 监听端口" + +msgid "Bind Interface" +msgstr "绑定接口" + +msgid "Network binding mode" +msgstr "网络绑定模式" + +msgid "LAN only" +msgstr "仅局域网" + +msgid "Loopback only" +msgstr "仅本地回环" + +msgid "All interfaces (WAN accessible)" +msgstr "所有接口(WAN 可访问)" + +msgid "Auto" +msgstr "自动" + +msgid "Config Terminal Port" +msgstr "配置终端端口" + +msgid "Web PTY terminal port for oc-config" +msgstr "oc-config Web PTY 终端端口" + +msgid "Node.js Version" +msgstr "Node.js 版本" + +msgid "Node.js version to download (requires v22+)" +msgstr "要下载的 Node.js 版本(需要 v22+)" + +msgid "Authentication" +msgstr "认证" + +msgid "Gateway Token" +msgstr "网关令牌" + +msgid "Authentication token for API access. Keep it secret." +msgstr "API 访问认证令牌,请妥善保管。" + +msgid "Reset Token" +msgstr "重置令牌" + +msgid "Generate New Token" +msgstr "生成新令牌" + +msgid "Are you sure you want to generate a new token? Current connections will be disconnected." +msgstr "确定要生成新令牌吗?当前连接将会断开。" + +msgid "Generating..." +msgstr "正在生成..." + +msgid "Token updated" +msgstr "令牌已更新" + +msgid "Quick Actions" +msgstr "快捷操作" + +msgid "Download Node.js and install OpenClaw" +msgstr "下载 Node.js 并安装 OpenClaw" + +msgid "Install Environment" +msgstr "安装环境" + +msgid "Restart Service" +msgstr "重启服务" + +msgid "Stop Service" +msgstr "停止服务" + +msgid "Advanced Configuration" +msgstr "高级配置" + +msgid "Executing..." +msgstr "正在执行..." + +msgid "completed" +msgstr "已完成" + +# ═══════════════════════════════════════════ +# model.lua — 模型设置页 +# ═══════════════════════════════════════════ + +msgid "Configure your AI model provider and API credentials. After saving, the configuration will be synced to OpenClaw." +msgstr "配置您的 AI 模型提供商和 API 凭证。保存后配置将自动同步到 OpenClaw。" + +msgid "AI Model Provider" +msgstr "AI 模型提供商" + +msgid "Provider" +msgstr "提供商" + +msgid "Select your AI model provider" +msgstr "选择您的 AI 模型提供商" + +msgid "-- Not configured --" +msgstr "-- 未配置 --" + +msgid "Multi-provider aggregator" +msgstr "多提供商聚合器" + +msgid "Custom OpenAI-compatible API" +msgstr "自定义 OpenAI 兼容 API" + +msgid "API Key" +msgstr "API 密钥" + +msgid "Your provider API key" +msgstr "您的提供商 API 密钥" + +msgid "API Base URL" +msgstr "API 基础地址" + +msgid "Custom OpenAI-compatible API endpoint" +msgstr "自定义 OpenAI 兼容 API 端点" + +msgid "Active Model" +msgstr "当前模型" + +msgid "Model" +msgstr "模型" + +msgid "Multimodal flagship (recommended)" +msgstr "多模态旗舰(推荐)" + +msgid "Cost effective" +msgstr "经济实惠" + +msgid "Reasoning flagship" +msgstr "推理旗舰" + +msgid "Reasoning lightweight" +msgstr "轻量推理" + +msgid "Reasoning classic" +msgstr "经典推理" + +msgid "Latest Sonnet (recommended)" +msgstr "最新 Sonnet(推荐)" + +msgid "Top reasoning" +msgstr "顶级推理" + +msgid "Fast" +msgstr "快速" + +msgid "Flagship reasoning (recommended)" +msgstr "旗舰推理(推荐)" + +msgid "Fast balanced" +msgstr "快速均衡" + +msgid "Low latency" +msgstr "低延迟" + +msgid "General chat" +msgstr "通用对话" + +msgid "Deep reasoning" +msgstr "深度推理" + +msgid "(ultra fast)" +msgstr "(超快)" + +msgid "Model Name" +msgstr "模型名称" + +msgid "For multi-provider setup, advanced model allowlist, or OAuth login (Qwen Portal, Gemini CLI), use the" +msgstr "如需多提供商配置、高级模型白名单或 OAuth 登录(Qwen Portal、Gemini CLI),请使用" + +msgid "page which provides the full interactive wizard." +msgstr "页面,其中提供完整的交互式配置向导。" + +# ═══════════════════════════════════════════ +# channel.lua — 渠道设置页 +# ═══════════════════════════════════════════ + +msgid "Configure messaging channels for OpenClaw. Telegram is most popular." +msgstr "配置 OpenClaw 的消息渠道。Telegram 是最常用的渠道。" + +msgid "Bot Token" +msgstr "Bot 令牌" + +msgid "Get from @BotFather on Telegram: /newbot → copy token" +msgstr "从 Telegram 的 @BotFather 获取:/newbot → 复制令牌" + +msgid "After setting Bot Token, restart the service, then send /start to your Bot on Telegram." +msgstr "设置 Bot 令牌后,重启服务,然后在 Telegram 上向您的 Bot 发送 /start。" + +msgid "For pairing wizard, go to" +msgstr "如需配对向导,请前往" + +msgid "Get from discord.com/developers/applications → Bot → Reset Token" +msgstr "从 discord.com/developers/applications → Bot → Reset Token 获取" + +msgid "Feishu (Lark)" +msgstr "飞书" + +msgid "App ID" +msgstr "应用 ID" + +msgid "Get from open.feishu.cn → Create App" +msgstr "从 open.feishu.cn → 创建应用 获取" + +msgid "App Secret" +msgstr "应用密钥" + +msgid "Get from api.slack.com/apps → Create App (xoxb-...)" +msgstr "从 api.slack.com/apps → Create App 获取(xoxb-...)" + +msgid "WhatsApp requires QR code pairing through the Web console." +msgstr "WhatsApp 需要通过 Web 控制台扫码配对。" + +msgid "After starting the service, visit:" +msgstr "启动服务后,请访问:" + +msgid "Then go to Channels → WhatsApp to scan QR code." +msgstr "然后进入 Channels → WhatsApp 扫描二维码。" + +msgid "For official interactive channel wizard, Telegram pairing helper, or Signal/Line/MS Teams configuration, use the" +msgstr "如需官方交互式渠道向导、Telegram 配对助手或 Signal/Line/MS Teams 配置,请使用" + +msgid "page." +msgstr "页面。" + +# ═══════════════════════════════════════════ +# status.htm — 状态面板 +# ═══════════════════════════════════════════ + +msgid "Service Status" +msgstr "服务状态" + +msgid "Status" +msgstr "状态" + +msgid "Loading..." +msgstr "加载中..." + +msgid "Gateway" +msgstr "网关" + +msgid "Config Terminal" +msgstr "配置终端" + +msgid "Memory" +msgstr "内存" + +msgid "Uptime" +msgstr "运行时间" + +msgid "Disabled" +msgstr "已禁用" + +msgid "Running" +msgstr "运行中" + +msgid "Stopped" +msgstr "已停止" + +msgid "Listening" +msgstr "监听中" + +msgid "Not listening" +msgstr "未监听" + +msgid "Not installed" +msgstr "未安装" + +msgid "Error" +msgstr "错误" + +# ═══════════════════════════════════════════ +# advanced.htm — 高级配置页 +# ═══════════════════════════════════════════ + +msgid "What is this?" +msgstr "这是什么?" + +msgid "This page embeds the OpenClaw interactive configuration terminal (oc-config). It provides the full-featured management menu including:" +msgstr "此页面嵌入了 OpenClaw 交互式配置终端(oc-config),提供完整的管理菜单,包括:" + +msgid "Multi-provider AI model setup with OAuth support" +msgstr "支持 OAuth 的多提供商 AI 模型配置" + +msgid "Telegram pairing wizard" +msgstr "Telegram 配对向导" + +msgid "Health check and diagnostics" +msgstr "健康检查和诊断" + +msgid "Raw configuration file editor" +msgstr "原始配置文件编辑器" + +msgid "Factory reset" +msgstr "恢复出厂设置" + +msgid "Configuration Terminal" +msgstr "配置终端" + +msgid "Checking..." +msgstr "检查中..." + +msgid "Reload" +msgstr "刷新" + +msgid "Connecting to configuration terminal..." +msgstr "正在连接配置终端..." + +msgid "Available menu options in terminal" +msgstr "终端中可用的菜单选项" + +msgid "View current config" +msgstr "查看当前配置" + +msgid "Configure AI model provider" +msgstr "配置 AI 模型提供商" + +msgid "Set active model" +msgstr "设置当前模型" + +msgid "Configure channels" +msgstr "配置消息渠道" + +msgid "pairing wizard" +msgstr "配对向导" + +msgid "Health check" +msgstr "健康检查" + +msgid "Restart Gateway" +msgstr "重启网关" + +msgid "View/edit raw config" +msgstr "查看/编辑原始配置" + +msgid "Reset to defaults" +msgstr "恢复默认设置" + +msgid "Connected" +msgstr "已连接" + +msgid "Terminal not running" +msgstr "终端未运行" + +msgid "Web PTY terminal is not running." +msgstr "Web PTY 终端未运行。" + +msgid "Please enable and start the service first from Basic Settings page." +msgstr "请先在基本设置页面启用并启动服务。" + +msgid "Failed to check terminal status" +msgstr "检查终端状态失败" + +msgid "Reconnecting..." +msgstr "正在重新连接..." + +# ═══════════════════════════════════════════ +# 其他 +# ═══════════════════════════════════════════ + +msgid "Port" +msgstr "端口" + +msgid "PID" +msgstr "进程 ID" + +msgid "Node.js" +msgstr "Node.js" + +msgid "Web Console" +msgstr "Web 控制台" + +msgid "Verify Token" +msgstr "验证令牌" + +msgid "Allow insecure auth" +msgstr "允许不安全认证" + +msgid "Disable device auth" +msgstr "禁用设备认证" + +msgid "Allow host header fallback" +msgstr "允许主机头回退" + +msgid "Docker sandbox" +msgstr "Docker 沙箱" + +msgid "Enable Docker sandbox for code execution" +msgstr "启用 Docker 沙箱执行代码" + +msgid "Node.js Mirror" +msgstr "Node.js 镜像源" + +msgid "China mirror (npmmirror.com)" +msgstr "中国镜像 (npmmirror.com)" + +msgid "Official (nodejs.org)" +msgstr "官方 (nodejs.org)" + +msgid "Check Environment" +msgstr "检查环境" + +msgid "Install / Upgrade" +msgstr "安装 / 升级" + +msgid "Telegram" +msgstr "Telegram" + +msgid "Discord" +msgstr "Discord" + +msgid "Feishu" +msgstr "飞书" + +msgid "Slack" +msgstr "Slack" + +msgid "WhatsApp" +msgstr "WhatsApp" + +msgid "Regenerate Token" +msgstr "重新生成令牌" + +msgid "Custom API Base URL" +msgstr "自定义 API 基础地址" + +msgid "Auth Token" +msgstr "认证令牌" + +msgid "Gateway authentication token" +msgstr "网关认证令牌" + +msgid "Web PTY terminal port for oc-config" +msgstr "oc-config Web PTY 终端端口" + +msgid "Select the AI model provider to use" +msgstr "选择要使用的 AI 模型提供商" diff --git a/root/etc/config/openclaw b/root/etc/config/openclaw new file mode 100644 index 0000000..6aba12e --- /dev/null +++ b/root/etc/config/openclaw @@ -0,0 +1,6 @@ +config openclaw 'main' + option enabled '0' + option port '18789' + option bind 'lan' + option token '' + option pty_port '18793' diff --git a/root/etc/init.d/openclaw b/root/etc/init.d/openclaw new file mode 100755 index 0000000..3d562aa --- /dev/null +++ b/root/etc/init.d/openclaw @@ -0,0 +1,330 @@ +#!/bin/sh /etc/rc.common +# luci-app-openclaw — procd init 脚本 + +USE_PROCD=1 +START=99 +STOP=10 + +EXTRA_COMMANDS="setup status_service restart_gateway" +EXTRA_HELP=" setup 下载 Node.js 并安装 OpenClaw + status_service 显示服务状态 + restart_gateway 仅重启 Gateway 实例 (不影响 Web PTY)" + +NODE_BASE="/opt/openclaw/node" +OC_GLOBAL="/opt/openclaw/global" +OC_DATA="/opt/openclaw/data" +NODE_BIN="${NODE_BASE}/bin/node" +CONFIG_FILE="${OC_DATA}/.openclaw/openclaw.json" + +get_oc_entry() { +local search_dirs="${OC_GLOBAL}/lib/node_modules/openclaw +${OC_GLOBAL}/node_modules/openclaw +${NODE_BASE}/lib/node_modules/openclaw" + +# pnpm 全局安装路径形如: $OC_GLOBAL/5/node_modules/openclaw +for ver_dir in "${OC_GLOBAL}"/*/node_modules/openclaw; do +[ -d "$ver_dir" ] && search_dirs="$search_dirs +$ver_dir" +done + +local d +echo "$search_dirs" | while read -r d; do +[ -z "$d" ] && continue +if [ -f "${d}/openclaw.mjs" ]; then +echo "${d}/openclaw.mjs" +return +elif [ -f "${d}/dist/cli.js" ]; then +echo "${d}/dist/cli.js" +return +fi +done +} + +patch_iframe_headers() { +# 移除 OpenClaw 网关的 X-Frame-Options 和 frame-ancestors 限制,允许 LuCI iframe 嵌入 +local gw_js +for f in $(find "${OC_GLOBAL}" -name "gateway-cli-*.js" -type f 2>/dev/null); do + if grep -q "X-Frame-Options.*DENY" "$f" 2>/dev/null; then + sed -i "s|res.setHeader(\"X-Frame-Options\", \"DENY\");|// res.setHeader(\"X-Frame-Options\", \"DENY\"); // patched by luci-app-openclaw|g" "$f" + sed -i "s|\"frame-ancestors 'none'\"|\"frame-ancestors *\"|g" "$f" + logger -t openclaw "Patched iframe headers in $f" + fi +done +} + +sync_uci_to_json() { +# 将 UCI 配置同步到 openclaw.json,同时确保 token 双向同步 +local port bind token +port=$(uci -q get openclaw.main.port || echo "18789") +bind=$(uci -q get openclaw.main.bind || echo "lan") +token=$(uci -q get openclaw.main.token || echo "") + +# 确保配置目录和文件存在 +mkdir -p "$(dirname "$CONFIG_FILE")" +if [ ! -f "$CONFIG_FILE" ]; then +echo '{}' > "$CONFIG_FILE" +fi + +# UCI 没有 token 时,尝试从已有的 JSON 读取 +if [ -z "$token" ] && [ -x "$NODE_BIN" ]; then + token=$("$NODE_BIN" -e " +try{const d=JSON.parse(require('fs').readFileSync('${CONFIG_FILE}','utf8')); +if(d.gateway&&d.gateway.auth&&d.gateway.auth.token)process.stdout.write(d.gateway.auth.token);}catch(e){} +" 2>/dev/null) +fi + +# 如果仍然没有 token,生成一个新的 +if [ -z "$token" ]; then + token=$(head -c 24 /dev/urandom | hexdump -e '24/1 "%02x"' 2>/dev/null || openssl rand -hex 24 2>/dev/null || echo "auto_$(date +%s)") +fi + +# 确保 token 写回 UCI +local uci_token +uci_token=$(uci -q get openclaw.main.token || echo "") +if [ "$uci_token" != "$token" ]; then + uci set openclaw.main.token="$token" + uci commit openclaw 2>/dev/null +fi + +# 使用 Node.js 写入 JSON (如果可用) +if [ -x "$NODE_BIN" ]; then +OC_SYNC_PORT="$port" OC_SYNC_BIND="$bind" OC_SYNC_TOKEN="$token" OC_SYNC_FILE="$CONFIG_FILE" \ +"$NODE_BIN" -e " +const fs=require('fs'); +const f=process.env.OC_SYNC_FILE; +let d={}; +try{d=JSON.parse(fs.readFileSync(f,'utf8'));}catch(e){} +if(!d.gateway)d.gateway={}; +d.gateway.port=parseInt(process.env.OC_SYNC_PORT)||18789; +d.gateway.bind=process.env.OC_SYNC_BIND||'lan'; +d.gateway.mode='local'; +if(!d.gateway.auth)d.gateway.auth={}; +d.gateway.auth.mode='token'; +d.gateway.auth.token=process.env.OC_SYNC_TOKEN||''; +if(!d.gateway.controlUi)d.gateway.controlUi={}; +d.gateway.controlUi.allowInsecureAuth=true; +d.gateway.controlUi.dangerouslyDisableDeviceAuth=true; +d.gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true; +// 清理 v2026.3.1+ 已废弃的字段,避免配置验证失败 +delete d.gateway.name; +delete d.gateway.bonjour; +delete d.gateway.plugins; +fs.writeFileSync(f,JSON.stringify(d,null,2)); +" 2>/dev/null +fi + +chown openclaw:openclaw "$CONFIG_FILE" 2>/dev/null || true +} + +start_service() { +local enabled port bind pty_port +config_load openclaw +config_get enabled main enabled "0" +config_get port main port "18789" +config_get bind main bind "lan" +config_get pty_port main pty_port "18793" + +[ "$enabled" = "1" ] || { +echo "openclaw 已禁用。请在 /etc/config/openclaw 中设置 enabled 为 1" +return 0 +} + +# 检查 Node.js +if [ ! -x "$NODE_BIN" ]; then +echo "未找到 Node.js: $NODE_BIN" +echo "请运行: openclaw-env setup" +return 1 +fi + +# 检查 openclaw 入口 +local oc_entry +oc_entry=$(get_oc_entry) +if [ -z "$oc_entry" ]; then +echo "OpenClaw 未安装。请运行: openclaw-env setup" +return 1 +fi + + # 同步 UCI 到 JSON + sync_uci_to_json + + # 修复数据目录权限 (防止 root 用户操作后留下无法读取的文件) + chown -R openclaw:openclaw "$OC_DATA" 2>/dev/null || true + + # Patch iframe 安全头,允许 LuCI 嵌入 + patch_iframe_headers + +# 将 UCI bind 映射到 openclaw gateway --bind 参数 +local gw_bind="loopback" +case "$bind" in +lan) gw_bind="lan" ;; +loopback) gw_bind="loopback" ;; +all) gw_bind="custom" ;; # custom = 0.0.0.0 +*) gw_bind="$bind" ;; +esac + +# 启动 OpenClaw Gateway (主服务, 前台运行) +procd_open_instance "gateway" +procd_set_param command "$NODE_BIN" "$oc_entry" gateway run \ +--port "$port" --bind "$gw_bind" +procd_set_param env \ +HOME="$OC_DATA" \ +OPENCLAW_HOME="$OC_DATA" \ +OPENCLAW_STATE_DIR="${OC_DATA}/.openclaw" \ +OPENCLAW_CONFIG_PATH="$CONFIG_FILE" \ +NODE_BASE="$NODE_BASE" \ +OC_GLOBAL="$OC_GLOBAL" \ +OC_DATA="$OC_DATA" \ +PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +procd_set_param user openclaw +procd_set_param respawn 3600 5 0 +procd_set_param stdout 1 +procd_set_param stderr 1 +procd_set_param pidfile /var/run/openclaw.pid +procd_close_instance + +# 启动 Web PTY 配置终端 (辅助服务) +# 生成 PTY 会话 token 用于 WebSocket 认证 +local pty_token +pty_token=$(head -c 16 /dev/urandom | hexdump -e '16/1 "%02x"' 2>/dev/null || openssl rand -hex 16 2>/dev/null || echo "pty_$(date +%s)") +uci set openclaw.main.pty_token="$pty_token" +uci commit openclaw 2>/dev/null + +procd_open_instance "pty" +procd_set_param command "$NODE_BIN" /usr/share/openclaw/web-pty.js +procd_set_param env \ +OC_CONFIG_PORT="$pty_port" \ +OC_PTY_TOKEN="$pty_token" \ +OC_CONFIG_SCRIPT="/usr/share/openclaw/oc-config.sh" \ +NODE_BASE="$NODE_BASE" \ +OC_GLOBAL="$OC_GLOBAL" \ +OC_DATA="$OC_DATA" \ +HOME="$OC_DATA" \ +OPENCLAW_HOME="$OC_DATA" \ +OPENCLAW_STATE_DIR="${OC_DATA}/.openclaw" \ +OPENCLAW_CONFIG_PATH="$CONFIG_FILE" \ +PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +procd_set_param respawn 3600 5 5 +procd_set_param stdout 1 +procd_set_param stderr 1 +procd_set_param pidfile /var/run/openclaw-pty.pid +procd_close_instance +} + +stop_service() { +# procd 会自动处理进程停止 +return 0 +} + +service_triggers() { +procd_add_reload_trigger "openclaw" +} + +reload_service() { +stop +start +} + +setup() { +echo "正在调用 openclaw-env setup..." +/usr/bin/openclaw-env setup +} + +restart_gateway() { +# 仅重启 Gateway procd 实例,不影响 Web PTY +# 使用 stop+start 而非 kill,可重置 procd crash loop 计数器 +local port +port=$(uci -q get openclaw.main.port || echo "18789") + +# 停止 gateway 实例 (通过 ubus,不影响 PTY 实例) +ubus call service stop '{"name":"openclaw","instance":"gateway"}' 2>/dev/null || true + +# 等待端口释放 +local i=0 +while [ $i -lt 8 ]; do + netstat -tln 2>/dev/null | grep -q ":${port} " || break + sleep 1; i=$((i+1)) +done + +# 重新启动整个服务 (procd 会重建 gateway 实例,同时保留 PTY 实例) +# procd 的 start_service 幂等:已运行的实例不会重复启动 +/etc/init.d/openclaw start >/dev/null 2>&1 +} + +status_service() { +local port pty_port +port=$(uci -q get openclaw.main.port || echo "18789") +pty_port=$(uci -q get openclaw.main.pty_port || echo "18793") + +echo "=== OpenClaw 服务状态 ===" + +# Node.js +if [ -x "$NODE_BIN" ]; then +echo "Node.js: $($NODE_BIN --version 2>/dev/null)" +else +echo "Node.js: 未安装" +fi + +# OpenClaw +local oc_entry +oc_entry=$(get_oc_entry) +if [ -n "$oc_entry" ]; then +local ver +ver=$("$NODE_BIN" "$oc_entry" --version 2>/dev/null | tr -d '[:space:]') +echo "OpenClaw: v${ver:-未知}" +else +echo "OpenClaw: 未安装" +fi + +# 端口检测函数 (ss 优先, 回退 netstat) +_check_port() { + local p="$1" + if command -v ss >/dev/null 2>&1; then + ss -tlnp 2>/dev/null | grep -q ":${p} " + else + netstat -tlnp 2>/dev/null | grep -q ":${p} " + fi +} + +_get_pid_by_port() { + local p="$1" + if command -v ss >/dev/null 2>&1; then + ss -tlnp 2>/dev/null | grep ":${p} " | head -1 | sed -n 's/.*pid=\([0-9]*\).*/\1/p' + else + netstat -tlnp 2>/dev/null | grep ":${p} " | head -1 | sed 's|.* \([0-9]*\)/.*|\1|' + fi +} + +# Gateway port +if _check_port "$port"; then +echo "网关: 运行中 (端口 $port)" +# PID +local pid +pid=$(_get_pid_by_port "$port") +if [ -n "$pid" ]; then +echo "进程ID: $pid" +# Memory +local rss +rss=$(awk '/VmRSS/{print $2}' /proc/$pid/status 2>/dev/null) +[ -n "$rss" ] && echo "内存: ${rss} kB" +# Uptime +local start_time now_time +start_time=$(stat -c %Y /proc/$pid 2>/dev/null || echo "0") +now_time=$(date +%s) +if [ "$start_time" -gt 0 ]; then +local uptime=$((now_time - start_time)) +local hours=$((uptime / 3600)) +local mins=$(( (uptime % 3600) / 60 )) +echo "运行时间: ${hours}小时 ${mins}分钟" +fi +fi +else +echo "网关: 已停止" +fi + +# PTY port +if _check_port "$pty_port"; then +echo "Web PTY: 运行中 (端口 $pty_port)" +else +echo "Web PTY: 已停止" +fi +} diff --git a/root/etc/uci-defaults/99-openclaw b/root/etc/uci-defaults/99-openclaw new file mode 100755 index 0000000..d81bcec --- /dev/null +++ b/root/etc/uci-defaults/99-openclaw @@ -0,0 +1,41 @@ +#!/bin/sh +# luci-app-openclaw — 首次安装初始化脚本 + +# 创建 openclaw 系统用户 (无 home, 无 shell) +if ! id openclaw >/dev/null 2>&1; then + # 动态查找可用 UID/GID (从 1000 开始,避免与已有用户冲突) + OC_UID=1000 + while grep -q "^[^:]*:x:${OC_UID}:" /etc/passwd 2>/dev/null; do + OC_UID=$((OC_UID + 1)) + done + OC_GID=$OC_UID + while grep -q "^[^:]*:x:${OC_GID}:" /etc/group 2>/dev/null; do + OC_GID=$((OC_GID + 1)) + done + # OpenWrt 方式:直接写入 /etc/passwd 和 /etc/shadow + if ! grep -q '^openclaw:' /etc/passwd 2>/dev/null; then + echo "openclaw:x:${OC_UID}:${OC_GID}:openclaw:/opt/openclaw/data:/bin/false" >> /etc/passwd + fi + if ! grep -q '^openclaw:' /etc/shadow 2>/dev/null; then + echo 'openclaw:x:0:0:99999:7:::' >> /etc/shadow + fi + if ! grep -q '^openclaw:' /etc/group 2>/dev/null; then + echo "openclaw:x:${OC_GID}:" >> /etc/group + fi +fi + +# 创建数据目录 +mkdir -p /opt/openclaw/data/.openclaw +mkdir -p /opt/openclaw/node +mkdir -p /opt/openclaw/global +chown -R openclaw:openclaw /opt/openclaw 2>/dev/null || true + +# 生成随机 Token (如果尚未设置) +CURRENT_TOKEN=$(uci -q get openclaw.main.token) +if [ -z "$CURRENT_TOKEN" ]; then + TOKEN=$(head -c 24 /dev/urandom | hexdump -e '24/1 "%02x"' 2>/dev/null || openssl rand -hex 24 2>/dev/null || echo "changeme_$(date +%s)") + uci set openclaw.main.token="$TOKEN" + uci commit openclaw +fi + +exit 0 diff --git a/root/usr/bin/openclaw-env b/root/usr/bin/openclaw-env new file mode 100755 index 0000000..1b8323e --- /dev/null +++ b/root/usr/bin/openclaw-env @@ -0,0 +1,478 @@ +#!/bin/sh +# ============================================================================ +# openclaw-env — Node.js 环境自动检测/下载 + OpenClaw 安装 +# 用法: +# openclaw-env setup — 完整安装 (Node.js + pnpm + OpenClaw) +# openclaw-env check — 检查环境状态 +# openclaw-env upgrade — 升级 OpenClaw 到最新版 +# openclaw-env node — 仅下载/更新 Node.js +# 环境变量: +# OC_VERSION — 指定 OpenClaw 版本 (如 2026.3.1),不设置则安装最新版 +# ============================================================================ +set -e + +NODE_VERSION="${NODE_VERSION:-22.16.0}" +# 经过验证的 OpenClaw 稳定版本 (更新此值需同步测试) +OC_TESTED_VERSION="2026.3.1" +# 用户可通过 OC_VERSION 环境变量覆盖安装版本 +OC_VERSION="${OC_VERSION:-}" +NODE_BASE="/opt/openclaw/node" +OC_GLOBAL="/opt/openclaw/global" +OC_DATA="/opt/openclaw/data" +NODE_BIN="${NODE_BASE}/bin/node" +NPM_BIN="${NODE_BASE}/bin/npm" +PNPM_BIN="${OC_GLOBAL}/bin/pnpm" + +# Node.js 官方镜像 + musl 非官方构建 +NODE_MIRROR="${NODE_MIRROR:-https://nodejs.org/dist}" +NODE_MIRROR_CN="https://npmmirror.com/mirrors/node" +NODE_MUSL_MIRROR="https://unofficial-builds.nodejs.org/download/release" + +export PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:$PATH" + +log_info() { echo " [✓] $1"; } +log_warn() { echo " [!] $1"; } +log_error() { echo " [✗] $1"; } + +# 检测 C 运行时类型 (glibc vs musl) +detect_libc() { + if ldd --version 2>&1 | grep -qi musl; then + echo "musl" + elif [ -f /lib/ld-musl-*.so.1 ] 2>/dev/null; then + echo "musl" + elif [ -f /etc/openwrt_release ] || grep -qi "openwrt\|istoreos\|lede" /etc/os-release 2>/dev/null; then + echo "musl" + else + echo "glibc" + fi +} + +# 在所有可能的位置查找 openclaw 入口文件 +# pnpm 全局安装路径形如: $OC_GLOBAL/5/node_modules/openclaw +find_oc_entry() { + local search_dirs="${OC_GLOBAL}/lib/node_modules/openclaw +${OC_GLOBAL}/node_modules/openclaw +${NODE_BASE}/lib/node_modules/openclaw" + + # 添加 pnpm 版本化目录 (如 /opt/openclaw/global/5/node_modules/openclaw) + for ver_dir in "${OC_GLOBAL}"/*/node_modules/openclaw; do + [ -d "$ver_dir" ] 2>/dev/null && search_dirs="$search_dirs +$ver_dir" + done + + local d + echo "$search_dirs" | while read -r d; do + [ -z "$d" ] && continue + if [ -f "${d}/openclaw.mjs" ]; then + echo "${d}/openclaw.mjs" + return + elif [ -f "${d}/dist/cli.js" ]; then + echo "${d}/dist/cli.js" + return + fi + done +} + +detect_arch() { + local arch + arch=$(uname -m) + case "$arch" in + x86_64) echo "linux-x64" ;; + aarch64) echo "linux-arm64" ;; + armv7l|armv6l) + log_error "不支持的 CPU 架构: $arch" + log_error "Node.js v22+ 不提供 32 位 ARM 预编译包。" + log_error "建议: 使用 aarch64 (ARM64) 版本的固件,或使用 x86_64 设备。" + exit 1 + ;; + *) + log_error "不支持的 CPU 架构: $arch (仅支持 x86_64/aarch64)" + exit 1 + ;; + esac +} + +download_node() { + local node_ver="$1" + local node_arch + node_arch=$(detect_arch) + local libc_type + libc_type=$(detect_libc) + + local tarball="" + local url="" url_fallback="" + + if [ "$libc_type" = "musl" ]; then + tarball="node-v${node_ver}-${node_arch}-musl.tar.xz" + url="${NODE_MUSL_MIRROR}/v${node_ver}/${tarball}" + url_fallback="" + echo "" + echo "=== 下载 Node.js v${node_ver} (${node_arch}, musl libc) ===" + else + tarball="node-v${node_ver}-${node_arch}.tar.xz" + url="${NODE_MIRROR}/v${node_ver}/${tarball}" + url_fallback="${NODE_MIRROR_CN}/v${node_ver}/${tarball}" + echo "" + echo "=== 下载 Node.js v${node_ver} (${node_arch}, glibc) ===" + fi + + local tmp_file="/tmp/${tarball}" + + # 如果已存在且版本正确, 跳过 + if [ -x "$NODE_BIN" ]; then + local current_ver + current_ver=$("$NODE_BIN" --version 2>/dev/null | sed 's/^v//') + if [ "$current_ver" = "$node_ver" ]; then + log_info "Node.js v${node_ver} 已安装, 跳过下载" + return 0 + fi + log_warn "当前 Node.js v${current_ver}, 将更新到 v${node_ver}" + fi + + # 下载 (带重试) + local downloaded=0 + local mirror_list="$url" + [ -n "$url_fallback" ] && mirror_list="$url $url_fallback" + for mirror_url in $mirror_list; do + echo " 正在从 ${mirror_url} 下载..." + if curl -fSL --connect-timeout 15 --max-time 300 -o "$tmp_file" "$mirror_url" 2>/dev/null || \ + wget -q --timeout=15 -O "$tmp_file" "$mirror_url" 2>/dev/null; then + downloaded=1 + break + fi + log_warn "下载失败, 尝试备用镜像..." + done + + if [ "$downloaded" -eq 0 ]; then + log_error "所有镜像均下载失败" + rm -f "$tmp_file" + exit 1 + fi + + # 解压 + echo " 正在解压到 ${NODE_BASE}..." + rm -rf "$NODE_BASE" + mkdir -p "$NODE_BASE" + tar xf "$tmp_file" -C "$NODE_BASE" --strip-components=1 + rm -f "$tmp_file" + + # 验证 + if [ -x "$NODE_BIN" ]; then + log_info "Node.js $($NODE_BIN --version) 安装成功" + else + log_error "Node.js 安装验证失败" + exit 1 + fi +} + +install_pnpm() { + echo "" + echo "=== 安装 pnpm ===" + + if [ -x "$PNPM_BIN" ]; then + log_info "pnpm 已安装: $($PNPM_BIN --version 2>/dev/null)" + return 0 + fi + + # 使用 npm 安装 pnpm 到全局目录 + mkdir -p "$OC_GLOBAL" + "$NPM_BIN" install -g pnpm --prefix="$OC_GLOBAL" 2>/dev/null + + if [ -x "$OC_GLOBAL/bin/pnpm" ]; then + PNPM_BIN="$OC_GLOBAL/bin/pnpm" + log_info "pnpm $($PNPM_BIN --version 2>/dev/null) 安装成功" + elif [ -x "$NODE_BASE/bin/pnpm" ]; then + PNPM_BIN="$NODE_BASE/bin/pnpm" + log_info "pnpm $($PNPM_BIN --version 2>/dev/null) 安装成功" + else + log_warn "pnpm 安装失败, 将使用 npm 作为回退" + fi +} + +install_openclaw() { + echo "" + echo "=== 安装 OpenClaw ===" + + # 确定安装版本 + local oc_pkg="openclaw" + if [ -n "$OC_VERSION" ]; then + oc_pkg="openclaw@${OC_VERSION}" + log_info "指定版本: v${OC_VERSION}" + else + oc_pkg="openclaw@latest" + log_info "安装最新版本" + fi + + local libc_type + libc_type=$(detect_libc) + + # musl 系统使用 npm + --ignore-scripts 避免 node-llama-cpp 编译失败 + # glibc 系统正常安装 + local install_flags="" + if [ "$libc_type" = "musl" ]; then + log_warn "检测到 musl libc,将跳过本地编译依赖 (不影响核心功能)" + install_flags="--ignore-scripts" + fi + + # 检查 git 是否可用 (openclaw 部分依赖可能使用 git:// 协议) + if ! command -v git >/dev/null 2>&1; then + log_warn "未检测到 git,正在尝试安装..." + opkg update >/dev/null 2>&1 + opkg install git git-http 2>&1 | tail -3 || true + if command -v git >/dev/null 2>&1; then + log_info "git 安装成功" + else + log_warn "git 安装失败,将尝试无 git 模式安装" + fi + fi + + # 优先用 npm 安装 (pnpm 在 musl 上全局安装可能有路径问题) + local npm_ok=0 + if [ -x "$NPM_BIN" ]; then + mkdir -p "$OC_GLOBAL" + "$NPM_BIN" install -g "$oc_pkg" --prefix="$OC_GLOBAL" $install_flags 2>&1 | tail -10 + # 检查是否安装成功 + if [ -n "$(find_oc_entry)" ]; then + npm_ok=1 + else + log_warn "首次安装未成功,尝试 --no-optional 模式重试..." + "$NPM_BIN" install -g "$oc_pkg" --prefix="$OC_GLOBAL" $install_flags --no-optional 2>&1 | tail -10 + [ -n "$(find_oc_entry)" ] && npm_ok=1 + fi + elif [ -x "$PNPM_BIN" ]; then + mkdir -p "$OC_GLOBAL" + "$PNPM_BIN" install -g "$oc_pkg" --prefix="$OC_GLOBAL" 2>&1 | tail -5 + else + log_error "npm 和 pnpm 均不可用" + exit 1 + fi + + # 验证 + local oc_ver="" + local oc_found + oc_found=$(find_oc_entry) + if [ -n "$oc_found" ]; then + oc_ver=$("$NODE_BIN" "$oc_found" --version 2>/dev/null | tr -d '[:space:]') + fi + + if [ -n "$oc_ver" ]; then + log_info "OpenClaw v${oc_ver} 安装成功" + else + log_error "OpenClaw 安装验证失败" + exit 1 + fi +} + +init_openclaw() { + echo "" + echo "=== 初始化 OpenClaw ===" + + # 创建数据目录 + mkdir -p "$OC_DATA/.openclaw" + + # 运行 onboard + local oc_entry="" + oc_entry=$(find_oc_entry) + + if [ -n "$oc_entry" ]; then + HOME="$OC_DATA" \ + OPENCLAW_HOME="$OC_DATA" \ + OPENCLAW_STATE_DIR="${OC_DATA}/.openclaw" \ + OPENCLAW_CONFIG_PATH="${OC_DATA}/.openclaw/openclaw.json" \ + "$NODE_BIN" "$oc_entry" onboard --non-interactive --accept-risk 2>/dev/null || true + log_info "初始化完成" + fi + + # 设置文件权限 + chown -R openclaw:openclaw "$OC_DATA" 2>/dev/null || true + chown -R openclaw:openclaw "$OC_GLOBAL" 2>/dev/null || true + chown -R openclaw:openclaw "$NODE_BASE" 2>/dev/null || true +} + +do_setup() { + local node_ver="$NODE_VERSION" + + # 检查是否已安装 + if [ -x "$NODE_BIN" ] && [ -n "$(find_oc_entry)" ]; then + local oc_ver="" + local oc_entry="$(find_oc_entry)" + local oc_pkg_dir="$(dirname "$oc_entry")" + [ -f "$oc_pkg_dir/package.json" ] && \ + oc_ver=$("$NODE_BIN" -e "try{console.log(require('$oc_pkg_dir/package.json').version)}catch(e){}" 2>/dev/null) || true + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ ⚠️ OpenClaw 运行环境已安装,无需重复安装 ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo "" + echo " Node.js: $($NODE_BIN --version 2>/dev/null)" + [ -n "$oc_ver" ] && echo " OpenClaw: v${oc_ver}" + echo "" + echo " 如需升级,请使用: openclaw-env upgrade" + echo " 如需重装,请先卸载: 在 LuCI 界面点击「卸载环境」" + echo "" + exit 0 + fi + + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ 一万AI分享 OpenClaw 环境安装 ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo "" + echo " 架构: $(uname -m)" + echo " Node 版本: v${node_ver}" + if [ -n "$OC_VERSION" ]; then + echo " OpenClaw: v${OC_VERSION} (稳定版)" + else + echo " OpenClaw: 最新版" + fi + echo " 安装路径: ${NODE_BASE}" + echo " 数据路径: ${OC_DATA}" + echo "" + + download_node "$node_ver" + install_pnpm + install_openclaw + init_openclaw + + echo "" + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ ✅ 安装完成! ║" + echo "║ ║" + echo "║ 下一步: ║" + echo "║ uci set openclaw.main.enabled=1 ║" + echo "║ uci commit openclaw ║" + echo "║ /etc/init.d/openclaw enable ║" + echo "║ /etc/init.d/openclaw start ║" + echo "║ ║" + echo "║ 或在 LuCI → 服务 → OpenClaw 中启用 ║" + echo "╚══════════════════════════════════════════════════════════════╝" +} + +do_check() { + echo "=== OpenClaw 环境检查 ===" + echo "" + + # Node.js + if [ -x "$NODE_BIN" ]; then + echo " Node.js: $($NODE_BIN --version 2>/dev/null)" + else + echo " Node.js: 未安装" + fi + + # pnpm + if [ -x "$PNPM_BIN" ]; then + echo " pnpm: $($PNPM_BIN --version 2>/dev/null)" + elif [ -x "${NODE_BASE}/bin/pnpm" ]; then + echo " pnpm: $(${NODE_BASE}/bin/pnpm --version 2>/dev/null)" + else + echo " pnpm: 未安装" + fi + + # OpenClaw + local oc_entry="" + oc_entry=$(find_oc_entry) + if [ -n "$oc_entry" ] && [ -x "$NODE_BIN" ]; then + echo " OpenClaw: v$($NODE_BIN $oc_entry --version 2>/dev/null | tr -d '[:space:]')" + else + echo " OpenClaw: 未安装" + fi + + # 配置文件 + if [ -f "$OC_DATA/.openclaw/openclaw.json" ]; then + echo " 配置: $OC_DATA/.openclaw/openclaw.json (存在)" + else + echo " 配置: 未初始化" + fi + + # 磁盘使用 + local used + used=$(du -sh /opt/openclaw 2>/dev/null | awk '{print $1}') + echo " 磁盘: ${used:-N/A}" + + # libc 类型 + echo " C库: $(detect_libc)" +} + +do_upgrade() { + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ 一万AI分享 OpenClaw 升级 ║" + echo "╚══════════════════════════════════════════════════════════════╝" + echo "" + + if [ ! -x "$NODE_BIN" ]; then + log_error "Node.js 未安装, 请先运行: openclaw-env setup" + exit 1 + fi + + # 获取当前版本 + local current_ver="" + local oc_entry="" + oc_entry=$(find_oc_entry) + if [ -n "$oc_entry" ]; then + local oc_pkg_dir="$(dirname "$oc_entry")" + [ -f "$oc_pkg_dir/package.json" ] && \ + current_ver=$("$NODE_BIN" -e "try{console.log(require('$oc_pkg_dir/package.json').version)}catch(e){}" 2>/dev/null) || true + fi + + echo " Node.js: $($NODE_BIN --version 2>/dev/null)" + [ -n "$current_ver" ] && echo " 当前版本: v${current_ver}" + echo "" + + local libc_type + libc_type=$(detect_libc) + local install_flags="" + [ "$libc_type" = "musl" ] && install_flags="--ignore-scripts" + + echo "=== 正在升级 OpenClaw ===" + echo "" + "$NPM_BIN" install -g openclaw@latest --prefix="$OC_GLOBAL" $install_flags 2>&1 + + # 验证升级结果 + local new_ver="" + local new_entry="" + new_entry=$(find_oc_entry) + if [ -n "$new_entry" ]; then + local new_pkg_dir="$(dirname "$new_entry")" + [ -f "$new_pkg_dir/package.json" ] && \ + new_ver=$("$NODE_BIN" -e "try{console.log(require('$new_pkg_dir/package.json').version)}catch(e){}" 2>/dev/null) || true + fi + + echo "" + if [ -n "$new_ver" ]; then + if [ "$current_ver" = "$new_ver" ]; then + log_info "当前已是最新版本 v${new_ver}" + else + log_info "升级成功: v${current_ver} → v${new_ver}" + fi + echo "" + echo "╔══════════════════════════════════════════════════════════════╗" + echo "║ ✅ 升级完成! ║" + echo "╚══════════════════════════════════════════════════════════════╝" + else + log_error "升级验证失败,OpenClaw 入口文件未找到" + exit 1 + fi +} + +# ── 主入口 ── +case "${1:-}" in + setup) + do_setup + ;; + check) + do_check + ;; + upgrade) + do_upgrade + ;; + node) + download_node "$NODE_VERSION" + ;; + *) + echo "用法: openclaw-env {setup|check|upgrade|node}" + echo "" + echo " setup — 完整安装 (下载 Node.js + pnpm + OpenClaw)" + echo " check — 检查环境状态" + echo " upgrade — 升级 OpenClaw 到最新版" + echo " node — 仅下载/更新 Node.js" + exit 1 + ;; +esac diff --git a/root/usr/share/openclaw/oc-config.sh b/root/usr/share/openclaw/oc-config.sh new file mode 100755 index 0000000..5009a01 --- /dev/null +++ b/root/usr/share/openclaw/oc-config.sh @@ -0,0 +1,1326 @@ +#!/bin/sh +# ============================================================================ +# OpenClaw 配置管理工具 — OpenWrt 适配版 +# 基于原始 oc-config.sh 移植,适配 ash/busybox 环境 +# ============================================================================ + +# ── 颜色 ── +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' +CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m' + +# ── 端口检查兼容函数 (ss 或 netstat) ── +# check_port_listening — 检查端口是否在监听,返回 0/1 +check_port_listening() { + local p="$1" + if command -v ss >/dev/null 2>&1; then + ss -ltn 2>/dev/null | grep -q ":${p} " + else + netstat -tln 2>/dev/null | grep -q ":${p} " + fi +} +# get_pid_by_port — 获取监听指定端口的进程 PID +get_pid_by_port() { + local p="$1" + if command -v ss >/dev/null 2>&1; then + ss -tlnp 2>/dev/null | grep ":${p} " | sed -n 's/.*pid=\([0-9]*\).*/\1/p' | head -1 + else + netstat -tlnp 2>/dev/null | grep ":${p} " | sed -n 's|.* \([0-9]*\)/.*|\1|p' | head -1 + fi +} + +# ── 路径 (OpenWrt 适配) ── +NODE_BASE="${NODE_BASE:-/opt/openclaw/node}" +OC_GLOBAL="${OC_GLOBAL:-/opt/openclaw/global}" +OC_DATA="${OC_DATA:-/opt/openclaw/data}" +NODE_BIN="${NODE_BASE}/bin/node" +OC_STATE_DIR="${OC_DATA}/.openclaw" +CONFIG_FILE="${OC_STATE_DIR}/openclaw.json" + +export HOME="$OC_DATA" +export OPENCLAW_HOME="$OC_DATA" +export OPENCLAW_STATE_DIR="$OC_STATE_DIR" +export OPENCLAW_CONFIG_PATH="$CONFIG_FILE" +export PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + +# ── 查找 openclaw 入口 ── +OC_PKG_DIR="" +for d in "${OC_GLOBAL}/lib/node_modules/openclaw" "${OC_GLOBAL}/node_modules/openclaw" "${NODE_BASE}/lib/node_modules/openclaw"; do + if [ -d "$d" ]; then + OC_PKG_DIR="$d" + break + fi +done + +OC_ENTRY="" +if [ -n "$OC_PKG_DIR" ]; then + if [ -f "${OC_PKG_DIR}/openclaw.mjs" ]; then + OC_ENTRY="${OC_PKG_DIR}/openclaw.mjs" + elif [ -f "${OC_PKG_DIR}/dist/cli.js" ]; then + OC_ENTRY="${OC_PKG_DIR}/dist/cli.js" + fi +fi + +oc_cmd() { + if [ -n "$OC_ENTRY" ] && [ -x "$NODE_BIN" ]; then + "$NODE_BIN" "$OC_ENTRY" "$@" 2>&1 + local rc=$? + # 修复权限: oc_cmd 以 root 运行但配置文件应属于 openclaw 用户 + chown openclaw:openclaw "$CONFIG_FILE" 2>/dev/null || true + chown openclaw:openclaw "${CONFIG_FILE}.bak" 2>/dev/null || true + return $rc + else + echo "ERROR: OpenClaw 未安装或 Node.js 不可用" + return 1 + fi +} + +# ── JSON 读写 (使用 Node.js) ── +json_get() { + if [ ! -f "$CONFIG_FILE" ]; then echo ""; return; fi + _JS_KEY="$1" "$NODE_BIN" -e " + const fs=require('fs'); + try{ + const d=JSON.parse(fs.readFileSync('${CONFIG_FILE}','utf8')); + const ks=process.env._JS_KEY.split('.');let v=d; + for(const k of ks){v=v[k];if(v===undefined){console.log('');process.exit(0);}} + if(typeof v==='object')console.log(JSON.stringify(v));else console.log(v); + }catch(e){console.log('');} + " 2>/dev/null +} + +json_set() { + local key="$1" value="$2" + if [ ! -f "$CONFIG_FILE" ]; then + mkdir -p "$(dirname "$CONFIG_FILE")" + echo '{}' > "$CONFIG_FILE" + fi + _JS_KEY="$key" _JS_VAL="$value" "$NODE_BIN" -e " + const fs=require('fs');let d={}; + try{d=JSON.parse(fs.readFileSync('${CONFIG_FILE}','utf8'));}catch(e){} + const ks=process.env._JS_KEY.split('.');let o=d; + for(let i=0;i/dev/null +} + +# ── 启用 auth 插件 ── +enable_auth_plugins() { + [ ! -f "$CONFIG_FILE" ] && return + "$NODE_BIN" -e " + const fs=require('fs'); + try{ + const d=JSON.parse(fs.readFileSync('${CONFIG_FILE}','utf8')); + if(!d.plugins)d.plugins={};if(!d.plugins.entries)d.plugins.entries={}; + const e=d.plugins.entries; + ['qwen-portal-auth','copilot-proxy','google-gemini-cli-auth','minimax-portal-auth'].forEach(p=>{ + if(!e[p])e[p]={};e[p].enabled=true; + }); + delete e['google-antigravity-auth']; + fs.writeFileSync('${CONFIG_FILE}',JSON.stringify(d,null,2)); + }catch(e){} + " 2>/dev/null +} + +# ── 辅助函数 ── + +# 清理输入: 去除 ANSI 转义序列、不可见字符,只保留 ASCII 可打印字符 +sanitize_input() { + # 1) tr -cd ' -~' : 只保留 ASCII 0x20-0x7E (去除 ESC/控制字符/Unicode 不可见字符) + # 2) sed : 去除 ESC 被剥离后残余的 CSI 序列 (如 bracketed paste 的 [200~ [201~) + # 3) sed : 去除首尾空白 + printf '%s' "$1" | tr -cd ' -~' | sed 's/\[[0-9;]*[a-zA-Z~]//g' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' +} + +prompt_with_default() { + local prompt="$1" default="$2" varname="$3" + if [ -n "$default" ]; then + printf " ${CYAN}${prompt} [${default}]:${NC} " >&2 + else + printf " ${CYAN}${prompt}:${NC} " >&2 + fi + read input + input=$(sanitize_input "$input") + local _result="${input:-$default}" + export "__prompt_result__=$_result" + eval "$varname=\"\$__prompt_result__\"" + unset __prompt_result__ +} + +confirm_yes() { + local ans="$1" + case "$ans" in y|Y|yes|YES|Yes) return 0 ;; *) return 1 ;; esac +} + +restart_gateway() { + echo "" + echo -e " ${YELLOW}正在重启 Gateway...${NC}" + + # 修复数据目录权限 (root 用户操作可能改变了文件属主) + chown -R openclaw:openclaw "$OC_DATA" 2>/dev/null || true + + local port + port=$(json_get gateway.port) + port=${port:-18789} + + # ── 使用 init.d restart_gateway: 只重启 Gateway 实例,不影响 PTY 终端 ── + # 发 SIGTERM 给 gateway 进程,procd 自动 respawn,避免 crash loop 计数累积 + /etc/init.d/openclaw restart_gateway >/dev/null 2>&1 + + # ── 等待端口监听,最多 60 秒 (Node.js 冷启动实测约 40 秒) ── + echo -e " ${YELLOW}⏳ Gateway 启动中,请稍候 (约 40 秒)...${NC}" + local waited=0 + while [ $waited -lt 60 ]; do + sleep 3 + waited=$((waited + 3)) + if check_port_listening "$port"; then + echo -e " ${GREEN}✅ Gateway 已重启成功 (${waited}秒)${NC}" + return 0 + fi + done + + # ── 超时仍未就绪: 先确认进程是否其实已经在运行 ── + # (可能端口刚好在轮询间隙启动完成) + if check_port_listening "$port"; then + echo -e " ${GREEN}✅ Gateway 已重启成功${NC}" + return 0 + fi + + # ── 确实未启动: 可能 procd crash loop 保护触发,用 start 解除 ── + echo -e " ${YELLOW}⏳ 正在尝试再次启动...${NC}" + /etc/init.d/openclaw start >/dev/null 2>&1 & + waited=0 + while [ $waited -lt 30 ]; do + sleep 3 + waited=$((waited + 3)) + if check_port_listening "$port"; then + echo -e " ${GREEN}✅ Gateway 已重启成功${NC}" + return 0 + fi + done + + echo -e " ${RED}❌ Gateway 可能未正常启动${NC}" + echo -e " ${CYAN} 查看日志: logread -e openclaw${NC}" +} + +ask_restart() { + prompt_with_default "是否立即重启 Gateway? (y/n)" "y" do_restart + confirm_yes "$do_restart" && restart_gateway +} + +# ── 查看当前配置 ── +show_current_config() { + echo "" + echo -e "${GREEN}┌──────────────────────────────────────────────────────────┐${NC}" + echo -e "${GREEN}│${NC} 📋 ${BOLD}当前配置概览${NC}" + echo -e "${GREEN}├──────────────────────────────────────────────────────────┤${NC}" + + local port=$(json_get gateway.port) + local bind=$(json_get gateway.bind) + local mode=$(json_get gateway.mode) + echo -e "${GREEN}│${NC} 网关端口 ............ ${CYAN}${port:-18789}${NC}" + echo -e "${GREEN}│${NC} 绑定模式 ............ ${CYAN}${bind:-lan}${NC}" + echo -e "${GREEN}│${NC} 运行模式 ............ ${CYAN}${mode:-local}${NC}" + + local model=$(json_get agents.defaults.model.primary) + if [ -n "$model" ]; then + echo -e "${GREEN}│${NC} 活跃模型 ............ ${CYAN}${model}${NC}" + else + echo -e "${GREEN}│${NC} 活跃模型 ............ ${YELLOW}未配置${NC}" + fi + + echo -e "${GREEN}├──────────────────────────────────────────────────────────┤${NC}" + echo -e "${GREEN}│${NC} ${BOLD}渠道配置状态${NC}" + + local tg_token=$(json_get channels.telegram.botToken) + local dc_token=$(json_get channels.discord.botToken) + local fs_appid=$(json_get channels.feishu.appId) + local sk_token=$(json_get channels.slack.botToken) + + if [ -n "$tg_token" ]; then + local tg_short=$(echo "$tg_token" | cut -c1-12) + echo -e "${GREEN}│${NC} Telegram ............ ${GREEN}✅ 已配置${NC} (${tg_short}...)" + else + echo -e "${GREEN}│${NC} Telegram ............ ${YELLOW}❌ 未配置${NC}" + fi + if [ -n "$dc_token" ]; then + echo -e "${GREEN}│${NC} Discord ............. ${GREEN}✅ 已配置${NC}" + else + echo -e "${GREEN}│${NC} Discord ............. ${YELLOW}❌ 未配置${NC}" + fi + if [ -n "$fs_appid" ]; then + local fs_short=$(echo "$fs_appid" | cut -c1-6) + echo -e "${GREEN}│${NC} 飞书 ................ ${GREEN}✅ 已配置${NC} (AppID: ${fs_short}...)" + else + echo -e "${GREEN}│${NC} 飞书 ................ ${YELLOW}❌ 未配置${NC}" + fi + if [ -n "$sk_token" ]; then + echo -e "${GREEN}│${NC} Slack ............... ${GREEN}✅ 已配置${NC}" + else + echo -e "${GREEN}│${NC} Slack ............... ${YELLOW}❌ 未配置${NC}" + fi + + echo -e "${GREEN}└──────────────────────────────────────────────────────────┘${NC}" + + echo "" + echo -e " ${BOLD}系统信息:${NC}" + echo -e " Node.js: $("$NODE_BIN" -v 2>/dev/null || echo '未安装')" + if [ -n "$OC_ENTRY" ]; then + echo -e " OpenClaw: $(oc_cmd --version 2>/dev/null || echo '未知')" + else + echo -e " OpenClaw: 未安装" + fi + echo -e " 架构: $(uname -m)" + local mem_total=$(awk '/MemTotal/{printf "%.0f", $2/1024}' /proc/meminfo 2>/dev/null || echo "?") + echo -e " 内存: ${mem_total} MB" +} + +# ══════════════════════════════════════════════════════════════ +# 配置 AI 模型 +# ══════════════════════════════════════════════════════════════ +configure_model() { + echo "" + echo -e " ${BOLD}🤖 配置 AI 模型提供商${NC}" + echo "" + echo -e " ${GREEN}${BOLD}--- 推荐 ---${NC}" + echo -e " ${CYAN}1)${NC} 🌟 官方完整模型配置向导 ${GREEN}(推荐,支持所有提供商)${NC}" + echo "" + echo -e " ${BOLD}--- 快速配置 ---${NC}" + echo -e " ${CYAN}2)${NC} OpenAI (GPT-5.2, GPT-5 mini, GPT-4.1)" + echo -e " ${CYAN}3)${NC} Anthropic (Claude Sonnet 4, Opus 4, Haiku)" + echo -e " ${CYAN}4)${NC} Google Gemini (Gemini 2.5 Pro/Flash, Gemini 3)" + echo -e " ${CYAN}5)${NC} OpenRouter (聚合多家模型)" + echo -e " ${CYAN}6)${NC} DeepSeek (DeepSeek-V3/R1)" + echo -e " ${CYAN}7)${NC} GitHub Copilot (需要 Copilot 订阅)" + echo -e " ${CYAN}8)${NC} 阿里云通义千问 Qwen (Portal/API)" + echo -e " ${CYAN}9)${NC} xAI Grok (Grok-3/3-mini)" + echo -e " ${CYAN}10)${NC} Groq (Llama 4, Llama 3.3)" + echo -e " ${CYAN}11)${NC} 硅基流动 SiliconFlow" + echo -e " ${CYAN}12)${NC} 自定义 OpenAI 兼容 API" + echo -e " ${CYAN}0)${NC} 返回" + echo "" + prompt_with_default "请选择" "1" choice + + case "$choice" in + 1) + echo "" + echo -e " ${CYAN}启动官方完整模型配置向导...${NC}" + echo -e " ${YELLOW}提示: ↑↓ 移动, Tab/空格 选中, 回车 确认${NC}" + echo "" + echo -e " ${CYAN}预启用模型认证插件...${NC}" + enable_auth_plugins + echo "" + # 检查并安装 gemini-cli (官方向导的 Google Gemini OAuth 依赖) + if ! command -v gemini >/dev/null 2>&1; then + local npm_bin="${NODE_BASE}/bin/npm" + if [ -x "$npm_bin" ]; then + echo -e " ${CYAN}安装 Gemini CLI (官方向导 Google OAuth 依赖)...${NC}" + "$npm_bin" install -g @google/gemini-cli --prefix="$OC_GLOBAL" >/dev/null 2>&1 || true + fi + fi + (oc_cmd configure --section model) || echo -e " ${YELLOW}配置向导已退出${NC}" + echo "" + ask_restart + ;; + 2) + echo "" + echo -e " ${BOLD}OpenAI 配置${NC}" + echo -e " ${YELLOW}获取 API Key: https://platform.openai.com/api-keys${NC}" + echo "" + prompt_with_default "请输入 OpenAI API Key (sk-...)" "" api_key + if [ -n "$api_key" ]; then + json_set models.openai.apiKey "$api_key" + echo "" + echo -e " ${CYAN}可用模型:${NC}" + echo -e " ${CYAN}a)${NC} gpt-5.2 — 最强编程与代理旗舰 (推荐)" + echo -e " ${CYAN}b)${NC} gpt-5-mini — 高性价比推理" + echo -e " ${CYAN}c)${NC} gpt-5-nano — 极速低成本" + echo -e " ${CYAN}d)${NC} gpt-4.1 — 最强非推理模型" + echo -e " ${CYAN}e)${NC} o3 — 推理模型" + echo -e " ${CYAN}f)${NC} o4-mini — 推理轻量" + echo -e " ${CYAN}g)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="gpt-5.2" ;; + b) model_name="gpt-5-mini" ;; + c) model_name="gpt-5-nano" ;; + d) model_name="gpt-4.1" ;; + e) model_name="o3" ;; + f) model_name="o4-mini" ;; + g) prompt_with_default "请输入模型名称" "gpt-5.2" model_name ;; + *) model_name="gpt-5.2" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ OpenAI 已配置,活跃模型: ${model_name}${NC}" + fi + ;; + 3) + echo "" + echo -e " ${BOLD}Anthropic 配置${NC}" + echo -e " ${YELLOW}获取 API Key: https://console.anthropic.com/settings/keys${NC}" + echo "" + prompt_with_default "请输入 Anthropic API Key (sk-ant-...)" "" api_key + if [ -n "$api_key" ]; then + json_set models.anthropic.apiKey "$api_key" + echo "" + echo -e " ${CYAN}可用模型:${NC}" + echo -e " ${CYAN}a)${NC} claude-sonnet-4-20250514 — Claude Sonnet 4 (推荐)" + echo -e " ${CYAN}b)${NC} claude-opus-4-20250514 — Claude Opus 4 顶级推理" + echo -e " ${CYAN}c)${NC} claude-haiku-4-20250514 — Claude Haiku 4 轻量快速" + echo -e " ${CYAN}d)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="claude-sonnet-4-20250514" ;; + b) model_name="claude-opus-4-20250514" ;; + c) model_name="claude-haiku-4-20250514" ;; + d) prompt_with_default "请输入模型名称" "claude-sonnet-4-20250514" model_name ;; + *) model_name="claude-sonnet-4-20250514" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ Anthropic 已配置,活跃模型: ${model_name}${NC}" + fi + ;; + 4) + echo "" + echo -e " ${BOLD}Google Gemini 配置${NC}" + echo -e " ${YELLOW}获取 API Key: https://aistudio.google.com/apikey${NC}" + echo "" + prompt_with_default "请输入 Google AI API Key" "" api_key + if [ -n "$api_key" ]; then + json_set models.google.apiKey "$api_key" + echo "" + echo -e " ${CYAN}可用模型:${NC}" + echo -e " ${CYAN}a)${NC} gemini-2.5-pro — 旗舰推理 (推荐)" + echo -e " ${CYAN}b)${NC} gemini-2.5-flash — 快速均衡" + echo -e " ${CYAN}c)${NC} gemini-2.5-flash-lite — 极速低成本" + echo -e " ${CYAN}d)${NC} gemini-3-flash — Gemini 3 预览版" + echo -e " ${CYAN}e)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="gemini-2.5-pro" ;; + b) model_name="gemini-2.5-flash" ;; + c) model_name="gemini-2.5-flash-lite" ;; + d) model_name="gemini-3-flash" ;; + e) prompt_with_default "请输入模型名称" "gemini-2.5-pro" model_name ;; + *) model_name="gemini-2.5-pro" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ Google Gemini 已配置,活跃模型: ${model_name}${NC}" + fi + ;; + 5) + echo "" + echo -e " ${BOLD}OpenRouter 配置${NC}" + echo -e " ${YELLOW}获取 API Key: https://openrouter.ai/keys${NC}" + echo -e " ${YELLOW}聚合多家模型,一个 Key 可调用所有主流模型${NC}" + echo "" + prompt_with_default "请输入 OpenRouter API Key" "" api_key + if [ -n "$api_key" ]; then + json_set models.openrouter.apiKey "$api_key" + echo "" + echo -e " ${CYAN}常用模型 (格式: provider/model):${NC}" + echo -e " ${CYAN}a)${NC} anthropic/claude-sonnet-4 — Claude Sonnet 4 (推荐)" + echo -e " ${CYAN}b)${NC} anthropic/claude-opus-4 — Claude Opus 4" + echo -e " ${CYAN}c)${NC} openai/gpt-5.2 — GPT-5.2" + echo -e " ${CYAN}d)${NC} google/gemini-2.5-pro — Gemini 2.5 Pro" + echo -e " ${CYAN}e)${NC} deepseek/deepseek-r1 — DeepSeek R1" + echo -e " ${CYAN}f)${NC} meta-llama/llama-4-maverick — Meta Llama 4" + echo -e " ${CYAN}g)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="anthropic/claude-sonnet-4" ;; + b) model_name="anthropic/claude-opus-4" ;; + c) model_name="openai/gpt-5.2" ;; + d) model_name="google/gemini-2.5-pro" ;; + e) model_name="deepseek/deepseek-r1" ;; + f) model_name="meta-llama/llama-4-maverick" ;; + g) prompt_with_default "请输入模型名称" "anthropic/claude-sonnet-4" model_name ;; + *) model_name="anthropic/claude-sonnet-4" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ OpenRouter 已配置,活跃模型: ${model_name}${NC}" + fi + ;; + 6) + echo "" + echo -e " ${BOLD}DeepSeek 配置${NC}" + echo -e " ${YELLOW}获取 API Key: https://platform.deepseek.com/api_keys${NC}" + echo "" + prompt_with_default "请输入 DeepSeek API Key" "" api_key + if [ -n "$api_key" ]; then + json_set models.deepseek.apiKey "$api_key" + echo "" + echo -e " ${CYAN}可用模型:${NC}" + echo -e " ${CYAN}a)${NC} deepseek-chat — DeepSeek-V3 (通用对话)" + echo -e " ${CYAN}b)${NC} deepseek-reasoner — DeepSeek-R1 (深度推理)" + echo -e " ${CYAN}c)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="deepseek-chat" ;; + b) model_name="deepseek-reasoner" ;; + c) prompt_with_default "请输入模型名称" "deepseek-chat" model_name ;; + *) model_name="deepseek-chat" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ DeepSeek 已配置,活跃模型: ${model_name}${NC}" + fi + ;; + 7) + echo "" + echo -e " ${BOLD}GitHub Copilot 配置${NC}" + echo -e " ${YELLOW}需要有效的 GitHub Copilot 订阅${NC}" + echo -e " ${YELLOW}获取 Token: https://github.com/settings/tokens (需 copilot 权限)${NC}" + echo "" + prompt_with_default "请输入 GitHub Token (ghp_...)" "" api_key + if [ -n "$api_key" ]; then + json_set models.github-copilot.apiKey "$api_key" + echo "" + echo -e " ${CYAN}可用模型:${NC}" + echo -e " ${CYAN}a)${NC} github-copilot/claude-sonnet-4 — Claude Sonnet 4 (推荐)" + echo -e " ${CYAN}b)${NC} github-copilot/gpt-5.2 — GPT-5.2" + echo -e " ${CYAN}c)${NC} github-copilot/gemini-2.5-pro — Gemini 2.5 Pro" + echo -e " ${CYAN}d)${NC} github-copilot/o3 — o3" + echo -e " ${CYAN}e)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="github-copilot/claude-sonnet-4" ;; + b) model_name="github-copilot/gpt-5.2" ;; + c) model_name="github-copilot/gemini-2.5-pro" ;; + d) model_name="github-copilot/o3" ;; + e) prompt_with_default "请输入模型名称" "github-copilot/claude-sonnet-4" model_name ;; + *) model_name="github-copilot/claude-sonnet-4" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ GitHub Copilot 已配置,活跃模型: ${model_name}${NC}" + fi + ;; + 8) + echo "" + echo -e " ${BOLD}阿里云通义千问 Qwen 配置${NC}" + echo -e " ${YELLOW}使用 OpenClaw 官方 Qwen Portal 认证插件${NC}" + echo "" + echo -e " ${CYAN}配置方式:${NC}" + echo -e " ${CYAN}a)${NC} 通过官方向导配置 (推荐)" + echo -e " ${CYAN}b)${NC} 通过 API Key 手动配置 (兼容 OpenAI 格式)" + echo "" + prompt_with_default "请选择" "b" qwen_mode + case "$qwen_mode" in + a) + echo "" + echo -e " ${CYAN}启用 Qwen Portal Auth 插件...${NC}" + enable_auth_plugins + echo -e " ${CYAN}启动 Qwen OAuth 授权...${NC}" + oc_cmd models auth login --provider qwen-portal --set-default || echo -e " ${YELLOW}OAuth 授权已退出${NC}" + echo "" + ask_restart + ;; + b|*) + echo "" + echo -e " ${YELLOW}获取 API Key: https://dashscope.console.aliyun.com/apiKey${NC}" + echo "" + prompt_with_default "请输入阿里云 API Key (sk-...)" "" api_key + if [ -n "$api_key" ]; then + json_set models.custom.apiKey "$api_key" + json_set models.custom.baseUrl "https://dashscope.aliyuncs.com/compatible-mode/v1" + echo "" + echo -e " ${CYAN}可用模型:${NC}" + echo -e " ${CYAN}a)${NC} qwen-max — 通义千问旗舰 (推荐)" + echo -e " ${CYAN}b)${NC} qwen-plus — 性价比之选" + echo -e " ${CYAN}c)${NC} qwen-turbo — 快速响应" + echo -e " ${CYAN}d)${NC} qwen3-235b-a22b — Qwen3 235B MoE" + echo -e " ${CYAN}e)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="qwen-max" ;; + b) model_name="qwen-plus" ;; + c) model_name="qwen-turbo" ;; + d) model_name="qwen3-235b-a22b" ;; + e) prompt_with_default "请输入模型名称" "qwen-max" model_name ;; + *) model_name="qwen-max" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ 通义千问已配置,活跃模型: ${model_name}${NC}" + fi + ;; + esac + ;; + 9) + echo "" + echo -e " ${BOLD}xAI Grok 配置${NC}" + echo -e " ${YELLOW}获取 API Key: https://console.x.ai${NC}" + echo "" + prompt_with_default "请输入 xAI API Key" "" api_key + if [ -n "$api_key" ]; then + json_set models.xai.apiKey "$api_key" + echo "" + echo -e " ${CYAN}可用模型:${NC}" + echo -e " ${CYAN}a)${NC} grok-3 — Grok 3 旗舰" + echo -e " ${CYAN}b)${NC} grok-3-mini — Grok 3 Mini" + echo -e " ${CYAN}c)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="grok-3" ;; + b) model_name="grok-3-mini" ;; + c) prompt_with_default "请输入模型名称" "grok-3" model_name ;; + *) model_name="grok-3" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ xAI Grok 已配置,活跃模型: ${model_name}${NC}" + fi + ;; + 10) + echo "" + echo -e " ${BOLD}Groq 配置${NC}" + echo -e " ${YELLOW}获取 API Key: https://console.groq.com/keys${NC}" + echo -e " ${YELLOW}Groq 提供超快推理速度${NC}" + echo "" + prompt_with_default "请输入 Groq API Key" "" api_key + if [ -n "$api_key" ]; then + json_set models.groq.apiKey "$api_key" + echo "" + echo -e " ${CYAN}可用模型:${NC}" + echo -e " ${CYAN}a)${NC} llama-4-maverick-17b-128e — Llama 4 Maverick (推荐)" + echo -e " ${CYAN}b)${NC} llama-3.3-70b-versatile — Llama 3.3 70B" + echo -e " ${CYAN}c)${NC} llama-3.1-8b-instant — Llama 3.1 8B (极速)" + echo -e " ${CYAN}d)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="llama-4-maverick-17b-128e" ;; + b) model_name="llama-3.3-70b-versatile" ;; + c) model_name="llama-3.1-8b-instant" ;; + d) prompt_with_default "请输入模型名称" "llama-4-maverick-17b-128e" model_name ;; + *) model_name="llama-4-maverick-17b-128e" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ Groq 已配置,活跃模型: ${model_name}${NC}" + fi + ;; + 11) + echo "" + echo -e " ${BOLD}硅基流动 SiliconFlow 配置${NC}" + echo -e " ${YELLOW}获取 API Key: https://cloud.siliconflow.cn/account/ak${NC}" + echo -e " ${YELLOW}国内推理平台,支持多种开源模型${NC}" + echo "" + prompt_with_default "请输入 SiliconFlow API Key" "" api_key + if [ -n "$api_key" ]; then + json_set models.custom.apiKey "$api_key" + json_set models.custom.baseUrl "https://api.siliconflow.cn/v1" + echo "" + echo -e " ${CYAN}可用模型:${NC}" + echo -e " ${CYAN}a)${NC} deepseek-ai/DeepSeek-V3 — DeepSeek V3 (推荐)" + echo -e " ${CYAN}b)${NC} deepseek-ai/DeepSeek-R1 — DeepSeek R1" + echo -e " ${CYAN}c)${NC} Qwen/Qwen3-235B-A22B — 通义千问 Qwen3 235B" + echo -e " ${CYAN}d)${NC} 手动输入模型名" + echo "" + prompt_with_default "请选择模型" "a" model_choice + case "$model_choice" in + a) model_name="deepseek-ai/DeepSeek-V3" ;; + b) model_name="deepseek-ai/DeepSeek-R1" ;; + c) model_name="Qwen/Qwen3-235B-A22B" ;; + d) prompt_with_default "请输入模型名称" "deepseek-ai/DeepSeek-V3" model_name ;; + *) model_name="deepseek-ai/DeepSeek-V3" ;; + esac + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ SiliconFlow 已配置,活跃模型: ${model_name}${NC}" + fi + ;; + 12) + echo "" + echo -e " ${BOLD}自定义 OpenAI 兼容 API${NC}" + echo -e " ${YELLOW}支持任何兼容 OpenAI API 格式的服务商${NC}" + echo "" + prompt_with_default "API Base URL (如 https://api.example.com/v1)" "" base_url + prompt_with_default "API Key" "" api_key + prompt_with_default "模型名称" "" model_name + if [ -n "$base_url" ] && [ -n "$api_key" ] && [ -n "$model_name" ]; then + json_set models.custom.apiKey "$api_key" + json_set models.custom.baseUrl "$base_url" + json_set agents.defaults.model.primary "$model_name" + echo -e " ${GREEN}✅ 自定义模型已配置${NC}" + fi + ;; + 0) return ;; + esac + + if [ "$choice" != "0" ] && [ "$choice" != "1" ] && [ "$choice" != "8" ]; then + echo "" + ask_restart + fi +} + +# ══════════════════════════════════════════════════════════════ +# 设定当前活跃模型 +# ══════════════════════════════════════════════════════════════ +set_active_model() { + echo "" + echo -e " ${BOLD}🔄 设定当前活跃模型${NC}" + echo "" + + local current_model=$(json_get agents.defaults.model.primary) + echo -e " 当前活跃模型: ${GREEN}${BOLD}${current_model:-未设置}${NC}" + echo "" + + local models_json="" + models_json=$(oc_cmd models list --json 2>/dev/null || echo "") + local model_count=0 + if [ -n "$models_json" ]; then + model_count=$("$NODE_BIN" -e " + try{const d=JSON.parse(process.argv[1]);console.log((d.models||[]).length);}catch(e){console.log(0);} + " "$models_json" 2>/dev/null || echo "0") + fi + + if [ "$model_count" -gt 0 ] 2>/dev/null; then + echo -e " ${CYAN}已配置的模型:${NC}" + echo "" + "$NODE_BIN" -e " + const d=JSON.parse(process.argv[1]); + (d.models||[]).forEach((m,i)=>{ + const mark=m.key===process.argv[2]?' ← 当前活跃':''; + const n=m.name&&m.name!==m.key?' ('+m.name+')':''; + console.log(' '+(i+1)+') '+m.key+n+mark); + }); + " "$models_json" "$current_model" 2>/dev/null + echo "" + echo -e " ${CYAN}m)${NC} 手动输入模型 ID" + echo -e " ${CYAN}0)${NC} 返回" + echo "" + prompt_with_default "请选择" "0" model_sel + + if [ "$model_sel" = "0" ]; then + return + elif [ "$model_sel" = "m" ]; then + prompt_with_default "请输入模型 ID (如 openai/gpt-4o)" "${current_model:-}" manual_model + if [ -n "$manual_model" ]; then + json_set agents.defaults.model.primary "$manual_model" + echo -e " ${GREEN}✅ 活跃模型已设为: ${manual_model}${NC}" + ask_restart + fi + elif echo "$model_sel" | grep -qE '^[0-9]+$'; then + local selected=$("$NODE_BIN" -e " + const d=JSON.parse(process.argv[1]); + const m=(d.models||[])[parseInt(process.argv[2])-1]; + console.log(m?m.key:''); + " "$models_json" "$model_sel" 2>/dev/null) + if [ -n "$selected" ]; then + json_set agents.defaults.model.primary "$selected" + echo -e " ${GREEN}✅ 活跃模型已切换为: ${selected}${NC}" + ask_restart + else + echo -e " ${YELLOW}无效选择${NC}" + fi + fi + else + echo -e " ${YELLOW}尚未配置任何模型。${NC}" + echo -e " ${YELLOW}请先通过「配置 AI 模型提供商」(菜单 2) 添加模型。${NC}" + echo "" + prompt_with_default "直接输入模型 ID 设置? (留空返回)" "" manual_model + if [ -n "$manual_model" ]; then + json_set agents.defaults.model.primary "$manual_model" + echo -e " ${GREEN}✅ 活跃模型已设为: ${manual_model}${NC}" + ask_restart + fi + fi +} + +# ══════════════════════════════════════════════════════════════ +# 配置 Telegram +# ══════════════════════════════════════════════════════════════ +configure_telegram() { + echo "" + echo -e " ${BOLD}📱 Telegram Bot 配置${NC}" + echo "" + echo -e " ${YELLOW}获取 Bot Token 步骤:${NC}" + echo -e " 1. 打开 Telegram → 搜索 ${CYAN}@BotFather${NC}" + echo -e " 2. 发送 ${CYAN}/newbot${NC} → 按提示创建" + echo -e " 3. 复制生成的 Token" + echo "" + + local current_token=$(json_get channels.telegram.botToken) + if [ -n "$current_token" ]; then + local ct_short=$(echo "$current_token" | cut -c1-12) + echo -e " ${GREEN}当前已配置 Token: ${ct_short}...${NC}" + fi + + prompt_with_default "请输入 Telegram Bot Token" "" tg_token + + if [ -n "$tg_token" ]; then + # ── 强力清洗: 先用 sanitize_input 去除 ANSI 转义序列,再白名单过滤 ── + tg_token=$(sanitize_input "$tg_token") + tg_token=$(printf '%s' "$tg_token" | tr -cd 'A-Za-z0-9:_-') + + # ── 格式验证: 使用 grep 正则匹配 "数字:字母数字" ── + if ! printf '%s' "$tg_token" | grep -qE '^[0-9]+:[A-Za-z0-9_-]+$'; then + echo -e " ${RED}❌ Token 格式错误${NC}" + echo -e " ${YELLOW} 正确格式: 123456789:ABCdefGHIjklMNOpqr${NC}" + echo -e " ${YELLOW} 请检查粘贴是否完整,重试。${NC}" + return + fi + + echo -e " ${CYAN}验证 Token...${NC}" + local verify="" + verify=$(curl -s --connect-timeout 5 --max-time 10 "https://api.telegram.org/bot${tg_token}/getMe" 2>/dev/null || echo '{"ok":false}') + if echo "$verify" | grep -q '"ok":true'; then + local bot_name=$(echo "$verify" | grep -o '"username":"[^"]*"' | head -1 | cut -d'"' -f4) + echo -e " ${GREEN}✅ Token 验证成功 — @${bot_name}${NC}" + else + echo -e " ${RED}❌ Token 验证失败${NC}" + echo -e " ${YELLOW} 可能原因: Token 不正确 或 无法连接 Telegram API${NC}" + prompt_with_default "是否仍然保存此 Token? (y/n)" "n" force_save + if ! confirm_yes "$force_save"; then + echo -e " ${YELLOW}已取消,Token 未保存。${NC}" + return + fi + fi + + # ── 使用 json_set 直接写入 (避免 oc_cmd CLI 参数解析问题) ── + json_set channels.telegram.botToken "$tg_token" + chown openclaw:openclaw "$CONFIG_FILE" 2>/dev/null || true + chown openclaw:openclaw "${CONFIG_FILE}.bak" 2>/dev/null || true + + # ── 保存后验证: 读回检查 Token 是否完整 ── + local saved_token=$(json_get channels.telegram.botToken) + if [ "$saved_token" != "$tg_token" ]; then + echo -e " ${RED}❌ Token 保存异常! 已保存的值与输入不一致${NC}" + echo -e " ${YELLOW} 期望: ${tg_token}${NC}" + echo -e " ${YELLOW} 实际: ${saved_token}${NC}" + echo -e " ${YELLOW} 请重新配置。${NC}" + return + fi + echo -e " ${GREEN}✅ Telegram Bot Token 已保存${NC}" + + # 重启 Gateway 使 Token 生效 + ask_restart + + # Token 保存且 Gateway 重启后,自动进入配对流程 + echo "" + echo -e " ${CYAN}接下来进行 Telegram 配对,让 Bot 关联您的账号。${NC}" + prompt_with_default "是否现在进行配对? (y/n)" "y" do_pair + if confirm_yes "$do_pair"; then + telegram_pairing + fi + else + echo -e " ${YELLOW}未输入 Token,已取消。${NC}" + fi +} + +# ── 配置 Discord ── +configure_discord() { + echo "" + echo -e " ${BOLD}🎮 Discord Bot 配置${NC}" + echo "" + echo -e " ${YELLOW}获取 Bot Token:${NC} ${CYAN}https://discord.com/developers/applications${NC}" + echo "" + prompt_with_default "请输入 Discord Bot Token" "" dc_token + dc_token=$(sanitize_input "$dc_token" | tr -d '[:space:]') + if [ -n "$dc_token" ]; then + json_set channels.discord.botToken "$dc_token" + chown openclaw:openclaw "$CONFIG_FILE" 2>/dev/null || true + echo -e " ${GREEN}✅ Discord Bot Token 已保存${NC}" + ask_restart + fi +} + +# ── 配置飞书 ── +configure_feishu() { + echo "" + echo -e " ${BOLD}🐦 飞书 Bot 配置${NC}" + echo "" + echo -e " ${YELLOW}获取凭据: ${CYAN}https://open.feishu.cn${NC} → 创建企业自建应用" + echo "" + + local current_appid=$(json_get channels.feishu.appId) + if [ -n "$current_appid" ]; then + echo -e " ${GREEN}当前 App ID: ${current_appid}${NC}" + fi + + prompt_with_default "请输入飞书 App ID" "" fs_appid + prompt_with_default "请输入飞书 App Secret" "" fs_secret + fs_appid=$(sanitize_input "$fs_appid" | tr -d '[:space:]') + fs_secret=$(sanitize_input "$fs_secret" | tr -d '[:space:]') + + if [ -n "$fs_appid" ] && [ -n "$fs_secret" ]; then + json_set channels.feishu.appId "$fs_appid" + json_set channels.feishu.appSecret "$fs_secret" + chown openclaw:openclaw "$CONFIG_FILE" 2>/dev/null || true + echo -e " ${GREEN}✅ 飞书配置已保存${NC}" + ask_restart + else + echo -e " ${YELLOW}信息不完整,已取消。${NC}" + fi +} + +# ── 配置 Slack ── +configure_slack() { + echo "" + echo -e " ${BOLD}💬 Slack Bot 配置${NC}" + echo "" + echo -e " ${YELLOW}获取 Bot Token:${NC} ${CYAN}https://api.slack.com/apps${NC} → Create App" + echo "" + prompt_with_default "请输入 Slack Bot Token (xoxb-...)" "" sk_token + sk_token=$(sanitize_input "$sk_token" | tr -d '[:space:]') + if [ -n "$sk_token" ]; then + json_set channels.slack.botToken "$sk_token" + chown openclaw:openclaw "$CONFIG_FILE" 2>/dev/null || true + echo -e " ${GREEN}✅ Slack Bot Token 已保存${NC}" + ask_restart + fi +} + +# ══════════════════════════════════════════════════════════════ +# Telegram 配对助手 +# ══════════════════════════════════════════════════════════════ +telegram_pairing() { + echo "" + echo -e " ${BOLD}🤝 Telegram 配对助手${NC}" + echo "" + + local tg_token=$(json_get channels.telegram.botToken) + if [ -z "$tg_token" ]; then + echo -e " ${YELLOW}未检测到 Telegram Bot Token,请先配置 Telegram。${NC}" + return + fi + + echo -e " ${CYAN}诊断 Telegram API 连通性...${NC}" + local verify="" + verify=$(curl -s --connect-timeout 5 --max-time 10 "https://api.telegram.org/bot${tg_token}/getMe" 2>/dev/null || echo '{"ok":false}') + if echo "$verify" | grep -q '"ok":true'; then + local bot_name=$(echo "$verify" | grep -o '"username":"[^"]*"' | head -1 | cut -d'"' -f4) + echo -e " ${GREEN}✅ Telegram API 连通正常 — @${bot_name}${NC}" + else + echo -e " ${RED}❌ Telegram API 连通检测未通过${NC}" + echo -e " ${YELLOW} 可能原因: Token 不正确、网络不通 或 Telegram 被屏蔽${NC}" + echo -e " ${CYAN} 建议: 返回重新配置 Token 或检查代理/网络设置${NC}" + return + fi + + echo "" + echo -e " ${GREEN}╔══════════════════════════════════════════════════╗${NC}" + echo -e " ${GREEN}║ 请在 Telegram 中向 Bot 发送 /start ║${NC}" + echo -e " ${GREEN}║ 然后回到这里按回车,脚本自动检测配对请求 ║${NC}" + echo -e " ${GREEN}╚══════════════════════════════════════════════════╝${NC}" + echo "" + echo -e " ${YELLOW}发送 /start 后按回车继续 (输入 q 退出)...${NC}" + read _wait + case "$_wait" in q|Q) return ;; esac + + local paired=0 + local attempt=1 + while [ $attempt -le 3 ]; do + echo -e " ${CYAN}检测配对请求... (第 ${attempt}/3 轮)${NC}" + local pair_json=$(oc_cmd pairing list telegram --json 2>/dev/null || echo "") + local codes="" + if [ -n "$pair_json" ]; then + codes=$(echo "$pair_json" | grep -o '"code"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4) + fi + + if [ -n "$codes" ]; then + # ash 不支持 <<<, 使用 echo | while + echo "$codes" | while IFS= read -r code; do + [ -z "$code" ] && continue + echo -e " ${CYAN}发现配对请求: ${code}${NC}" + local approve=$(oc_cmd pairing approve telegram "$code" 2>&1) + if echo "$approve" | grep -qi "approved\|success\|ok"; then + echo "" + echo -e " ${GREEN}${BOLD}🎉 Telegram 配对成功!${NC}" + fi + done + # 检查是否还有待配对的 + local re_check=$(oc_cmd pairing list telegram --json 2>/dev/null || echo "") + local re_codes=$(echo "$re_check" | grep -o '"code"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4) + if [ -z "$re_codes" ]; then + paired=1 + break + fi + fi + + if [ $attempt -lt 3 ] && [ $paired -eq 0 ]; then + echo -e " ${YELLOW}未检测到,等待 8 秒后重试...${NC}" + sleep 8 + fi + attempt=$((attempt + 1)) + done + + if [ "$paired" -eq 0 ]; then + echo "" + echo -e " ${YELLOW}未自动检测到配对请求。${NC}" + echo -e " ${CYAN}如果 Bot 已回复配对码,请手动输入 (回车跳过):${NC}" + prompt_with_default "配对码" "" manual_code + if [ -n "$manual_code" ]; then + local approve=$(oc_cmd pairing approve telegram "$manual_code" 2>&1) + if echo "$approve" | grep -qi "approved\|success\|ok"; then + echo -e " ${GREEN}${BOLD}🎉 Telegram 配对成功!${NC}" + else + echo -e " ${YELLOW}配对失败: $approve${NC}" + fi + fi + fi +} + +# ══════════════════════════════════════════════════════════════ +# 配置渠道子菜单 +# ══════════════════════════════════════════════════════════════ +configure_channels() { + while true; do + echo "" + echo -e " ${BOLD}📡 配置消息渠道${NC}" + echo "" + echo -e " ${CYAN}1)${NC} Telegram ${GREEN}(最常用,推荐)${NC}" + echo -e " ${CYAN}2)${NC} Discord" + echo -e " ${CYAN}3)${NC} 飞书 (Feishu)" + echo -e " ${CYAN}4)${NC} Slack" + echo -e " ${CYAN}5)${NC} WhatsApp ${YELLOW}(需通过 Web 控制台扫码)${NC}" + echo -e " ${CYAN}6)${NC} Telegram 配对助手" + echo -e " ${CYAN}7)${NC} 官方完整渠道配置向导" + echo -e " ${CYAN}0)${NC} 返回主菜单" + echo "" + prompt_with_default "请选择" "1" ch_choice + + case "$ch_choice" in + 1) configure_telegram ;; + 2) configure_discord ;; + 3) configure_feishu ;; + 4) configure_slack ;; + 5) + echo "" + echo -e " ${YELLOW}WhatsApp 需要通过 Web 控制台扫码配对:${NC}" + local gw_token=$(json_get gateway.auth.token) + local gw_port=$(json_get gateway.port) + gw_port=${gw_port:-18789} + echo -e " ${CYAN}http://<你的路由器IP>:${gw_port}/?token=${gw_token}${NC}" + echo -e " 打开后进入 Channels → WhatsApp 扫码即可。" + ;; + 6) telegram_pairing ;; + 7) + echo "" + echo -e " ${CYAN}启动官方渠道配置向导...${NC}" + (oc_cmd configure --section channels) || echo -e " ${YELLOW}配置向导已退出${NC}" + ;; + 0) return ;; + *) echo -e " ${YELLOW}无效选择${NC}" ;; + esac + done +} + +# ══════════════════════════════════════════════════════════════ +# 健康检查 +# ══════════════════════════════════════════════════════════════ +health_check() { + echo "" + echo -e " ${BOLD}🔍 健康检查${NC}" + echo "" + + local gw_port=$(json_get gateway.port) + gw_port=${gw_port:-18789} + + if check_port_listening "$gw_port"; then + echo -e " ${GREEN}✅ Gateway 端口 ${gw_port} 正在监听${NC}" + else + echo -e " ${RED}❌ Gateway 端口 ${gw_port} 未监听${NC}" + fi + + local http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 "http://127.0.0.1:${gw_port}/" 2>/dev/null || echo "000") + if [ "$http_code" = "200" ] || [ "$http_code" = "302" ] || [ "$http_code" = "401" ]; then + echo -e " ${GREEN}✅ HTTP 响应正常 (${http_code})${NC}" + else + echo -e " ${RED}❌ HTTP 响应异常 (${http_code})${NC}" + fi + + if [ -f "$CONFIG_FILE" ]; then + echo -e " ${GREEN}✅ 配置文件存在${NC}" + else + echo -e " ${RED}❌ 配置文件不存在${NC}" + fi + + echo "" + echo -e " ${CYAN}运行官方诊断...${NC}" + oc_cmd doctor 2>/dev/null || true + + echo "" + echo -e " ${CYAN}最近日志 (最后 10 行):${NC}" + logread -e openclaw 2>/dev/null | tail -10 || echo " (无日志)" +} + +# ══════════════════════════════════════════════════════════════ +# 恢复默认配置 +# ══════════════════════════════════════════════════════════════ +reset_to_defaults() { + echo "" + echo -e " ${BOLD}⚠️ 恢复默认配置${NC}" + echo "" + echo -e " ${YELLOW}请选择恢复级别:${NC}" + echo "" + echo -e " ${CYAN}1)${NC} 🔧 仅重置网关设置 (端口/绑定/模式恢复默认,保留模型和渠道)" + echo -e " ${CYAN}2)${NC} 🤖 清除模型配置 (移除所有 AI 模型和 API Key)" + echo -e " ${CYAN}3)${NC} 📡 清除渠道配置 (移除所有消息渠道配置)" + echo -e " ${CYAN}4)${NC} 🔄 完全恢复出厂 (删除所有配置,重新初始化)" + echo -e " ${CYAN}0)${NC} 返回" + echo "" + prompt_with_default "请选择" "0" reset_choice + + case "$reset_choice" in + 1) + echo "" + echo -e " ${YELLOW}将重置: 网关端口→18789, 绑定→lan, 模式→local${NC}" + echo -e " ${YELLOW}保留: 认证令牌、模型配置、消息渠道${NC}" + prompt_with_default "确认恢复网关默认设置? (yes/no)" "no" confirm + if [ "$confirm" = "yes" ]; then + echo "" + echo -e " ${CYAN}正在重置网关设置...${NC}" + json_set gateway.port 18789 2>&1 + json_set gateway.bind lan 2>&1 + json_set gateway.mode local 2>&1 + json_set gateway.controlUi.allowInsecureAuth true 2>&1 + json_set gateway.controlUi.dangerouslyDisableDeviceAuth true 2>&1 + json_set gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback true 2>&1 + json_set gateway.tailscale.mode off 2>&1 + echo -e " ${GREEN}✅ 网关设置已恢复默认${NC}" + ask_restart + else + echo -e " ${CYAN}已取消${NC}" + fi + ;; + 2) + echo "" + echo -e " ${RED}⚠️ 将清除: 所有模型配置、API Key、活跃模型设置${NC}" + prompt_with_default "确认清除所有模型配置? (yes/no)" "no" confirm + if [ "$confirm" = "yes" ]; then + echo "" + echo -e " ${CYAN}正在清除模型配置...${NC}" + oc_cmd config unset models >/dev/null 2>&1 || true + oc_cmd config unset agents.defaults.model >/dev/null 2>&1 || true + oc_cmd config unset agents.defaults.models >/dev/null 2>&1 || true + echo -e " ${GREEN}✅ 模型配置已清除${NC}" + echo -e " ${YELLOW}请通过菜单 [2] 重新配置 AI 模型${NC}" + ask_restart + else + echo -e " ${CYAN}已取消${NC}" + fi + ;; + 3) + echo "" + echo -e " ${RED}⚠️ 将清除: 所有消息渠道配置 (Telegram/Discord/飞书等)${NC}" + prompt_with_default "确认清除所有渠道配置? (yes/no)" "no" confirm + if [ "$confirm" = "yes" ]; then + echo "" + echo -e " ${CYAN}正在清除渠道配置...${NC}" + oc_cmd config unset channels >/dev/null 2>&1 || true + echo -e " ${GREEN}✅ 渠道配置已清除${NC}" + echo -e " ${YELLOW}请通过菜单 [4] 重新配置消息渠道${NC}" + ask_restart + else + echo -e " ${CYAN}已取消${NC}" + fi + ;; + 4) + echo "" + echo -e " ${RED}╔══════════════════════════════════════════════════════╗${NC}" + echo -e " ${RED}║ ⚠️ 完全恢复出厂设置 ║${NC}" + echo -e " ${RED}║ 此操作将删除所有配置并重新初始化 ║${NC}" + echo -e " ${RED}╚══════════════════════════════════════════════════════╝${NC}" + echo "" + echo -e " ${RED}此操作不可撤销!${NC}" + prompt_with_default "输入 RESET 确认恢复出厂设置" "" confirm + if [ "$confirm" = "RESET" ]; then + echo "" + echo -e " ${CYAN}[1/5] 停止 Gateway...${NC}" + # 只停止 gateway 实例, 不能停 pty (否则会断开当前终端连接) + local gw_pid="" + gw_pid=$(ubus call service list '{"name":"openclaw"}' 2>/dev/null | jsonfilter -e '$.openclaw.instances.gateway.pid' 2>/dev/null) || true + if [ -n "$gw_pid" ] && kill -0 "$gw_pid" 2>/dev/null; then + kill "$gw_pid" 2>/dev/null || true + sleep 2 + else + # 按端口查找 gateway 进程 + local gw_port_cur=$(json_get gateway.port) + gw_port_cur=${gw_port_cur:-18789} + local gw_pid2=$(get_pid_by_port "$gw_port_cur") + if [ -n "$gw_pid2" ]; then + kill "$gw_pid2" 2>/dev/null || true + sleep 2 + fi + fi + echo -e " ${GREEN} Gateway 已停止${NC}" + + echo -e " ${CYAN}[2/5] 备份当前配置...${NC}" + local backup_dir="${OC_STATE_DIR}/backups" + local backup_ts=$(date +%Y%m%d_%H%M%S) + mkdir -p "$backup_dir" + if [ -f "$CONFIG_FILE" ]; then + cp "$CONFIG_FILE" "${backup_dir}/openclaw_${backup_ts}.json" + echo -e " ${GREEN} 备份已保存: backups/openclaw_${backup_ts}.json${NC}" + fi + + echo -e " ${CYAN}[3/5] 重置配置...${NC}" + # 直接删除配置文件 (避免 oc_cmd reset 可能的交互式阻塞) + rm -f "$CONFIG_FILE" 2>/dev/null || true + rm -f "${CONFIG_FILE}.bak" 2>/dev/null || true + echo '{}' > "$CONFIG_FILE" + chown openclaw:openclaw "$CONFIG_FILE" 2>/dev/null || true + echo -e " ${GREEN} 配置已清除${NC}" + + echo -e " ${CYAN}[4/5] 重新初始化...${NC}" + # 尝试 onboard,超时 10 秒避免阻塞 + timeout 10 sh -c "$(which node 2>/dev/null || echo "$NODE_BIN") \"$OC_ENTRY\" onboard --non-interactive --accept-risk" >/dev/null 2>&1 || true + echo -e " ${GREEN} 初始化完成${NC}" + + echo -e " ${CYAN}[5/5] 应用 OpenWrt 适配配置...${NC}" + local new_token + new_token=$(head -c 24 /dev/urandom | hexdump -e '24/1 "%02x"' 2>/dev/null || dd if=/dev/urandom bs=24 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n' | head -c 48) + json_set gateway.port 18789 + json_set gateway.bind lan + json_set gateway.mode local + json_set gateway.auth.mode token + json_set gateway.auth.token "$new_token" + json_set gateway.controlUi.allowInsecureAuth true + json_set gateway.controlUi.dangerouslyDisableDeviceAuth true + json_set gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback true + json_set gateway.tailscale.mode off + + # 同步 token 到 UCI + . /lib/functions.sh 2>/dev/null || true + uci set openclaw.main.token="$new_token" 2>/dev/null + uci commit openclaw 2>/dev/null + + echo "" + echo -e " ${GREEN}✅ 出厂设置已恢复!${NC}" + echo "" + echo -e " ${CYAN}新认证令牌: ${new_token}${NC}" + echo "" + + # 重启 gateway (通过 procd reload, 这样不会杀 pty) + /etc/init.d/openclaw start >/dev/null 2>&1 & + echo -e " ${YELLOW}⏳ Gateway 启动中,请稍候...${NC}" + local gw_port=18789 + local waited=0 + while [ $waited -lt 15 ]; do + sleep 2 + waited=$((waited + 2)) + if check_port_listening "$gw_port"; then + echo -e " ${GREEN}✅ Gateway 已重新启动${NC}" + break + fi + done + if [ $waited -ge 15 ]; then + echo -e " ${YELLOW}⏳ Gateway 可能仍在启动中,请稍后检查${NC}" + fi + else + echo -e " ${CYAN}已取消${NC}" + fi + ;; + 0|"") return ;; + *) echo -e " ${YELLOW}无效选择${NC}" ;; + esac +} + +# ══════════════════════════════════════════════════════════════ +# 主菜单 +# ══════════════════════════════════════════════════════════════ +main_menu() { + while true; do + echo "" + echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}" + echo -e "${GREEN}║${NC} ${BOLD}OpenClaw AI Gateway — OpenWrt 配置管理${NC} ${GREEN}║${NC}" + echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}" + echo "" + echo -e " ${CYAN}1)${NC} 📋 查看当前配置" + echo -e " ${CYAN}2)${NC} 🤖 配置 AI 模型提供商" + echo -e " ${CYAN}3)${NC} 🔄 设定当前活跃模型" + echo -e " ${CYAN}4)${NC} 📡 配置消息渠道 (Telegram/Discord/飞书/Slack)" + echo -e " ${CYAN}5)${NC} 🤝 Telegram 配对助手" + echo -e " ${CYAN}6)${NC} 🔍 健康检查 / 诊断" + echo -e " ${CYAN}7)${NC} 🔄 重启 Gateway" + echo -e " ${CYAN}8)${NC} 📝 查看原始配置文件" + echo -e " ${CYAN}9)${NC} ⚠️ 恢复默认配置" + echo -e " ${CYAN}0)${NC} 退出" + echo "" + prompt_with_default "请选择" "1" menu_choice + + case "$menu_choice" in + 1) show_current_config ;; + 2) configure_model ;; + 3) set_active_model ;; + 4) configure_channels ;; + 5) telegram_pairing ;; + 6) health_check ;; + 7) restart_gateway ;; + 8) + echo "" + echo -e " ${CYAN}配置文件路径: ${CONFIG_FILE}${NC}" + echo "" + if [ -f "$CONFIG_FILE" ]; then + "$NODE_BIN" -e "console.log(JSON.stringify(JSON.parse(require('fs').readFileSync('${CONFIG_FILE}','utf8')),null,2))" 2>/dev/null || cat "$CONFIG_FILE" + else + echo " (配置文件不存在)" + fi + echo "" + prompt_with_default "是否用 vi 编辑? (y/n)" "n" do_edit + if confirm_yes "$do_edit"; then + vi "$CONFIG_FILE" + ask_restart + fi + ;; + 9) reset_to_defaults ;; + 0) + echo -e " ${GREEN}再见!${NC}" + exit 0 + ;; + *) echo -e " ${YELLOW}无效选择${NC}" ;; + esac + done +} + +# ── 支持命令行参数 ── +case "${1:-}" in + --set) + if [ -n "${2:-}" ] && [ -n "${3:-}" ]; then + json_set "$2" "$3" + chown openclaw:openclaw "$CONFIG_FILE" 2>/dev/null || true + echo -e "${GREEN}✅ 已设置 $2${NC}" + else + echo "用法: oc-config.sh --set " + fi + ;; + --get) + if [ -n "${2:-}" ]; then + oc_cmd config get "$2" + else + echo "用法: oc-config.sh --get " + fi + ;; + --restart) + restart_gateway + ;; + --status) + show_current_config + health_check + ;; + --help|-h) + echo "" + echo "OpenClaw AI Gateway — OpenWrt 配置管理工具" + echo "" + echo "用法:" + echo " oc-config.sh # 进入交互式菜单" + echo " oc-config.sh --set K V # 设置配置项" + echo " oc-config.sh --get K # 读取配置项" + echo " oc-config.sh --restart # 重启 Gateway" + echo " oc-config.sh --status # 查看状态" + echo "" + ;; + "") + main_menu + ;; + *) + echo "未知参数: $1 (使用 --help 查看帮助)" + exit 1 + ;; +esac diff --git a/root/usr/share/openclaw/ui/images/icon_256.png b/root/usr/share/openclaw/ui/images/icon_256.png new file mode 100644 index 0000000..2a8db4c Binary files /dev/null and b/root/usr/share/openclaw/ui/images/icon_256.png differ diff --git a/root/usr/share/openclaw/ui/images/icon_64.png b/root/usr/share/openclaw/ui/images/icon_64.png new file mode 100644 index 0000000..8bbf006 Binary files /dev/null and b/root/usr/share/openclaw/ui/images/icon_64.png differ diff --git a/root/usr/share/openclaw/ui/index.html b/root/usr/share/openclaw/ui/index.html new file mode 100644 index 0000000..18d8df1 --- /dev/null +++ b/root/usr/share/openclaw/ui/index.html @@ -0,0 +1,280 @@ + + + + + +一万AI分享 OpenClaw 配置管理 + + + + +
+ + ● 连接中... + +
+ +
+
+

🦞 一万AI分享 OpenClaw 配置管理工具

+

正在连接终端...

+
+
+ +
+ +
+

⚡ 连接已断开

+

配置脚本已退出或连接中断

+ +
+ + + + + + + + + diff --git a/root/usr/share/openclaw/ui/lib/addon-fit.min.js b/root/usr/share/openclaw/ui/lib/addon-fit.min.js new file mode 100644 index 0000000..9f4e48c --- /dev/null +++ b/root/usr/share/openclaw/ui/lib/addon-fit.min.js @@ -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 \ No newline at end of file diff --git a/root/usr/share/openclaw/ui/lib/addon-web-links.min.js b/root/usr/share/openclaw/ui/lib/addon-web-links.min.js new file mode 100644 index 0000000..cdfd584 --- /dev/null +++ b/root/usr/share/openclaw/ui/lib/addon-web-links.min.js @@ -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{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 \ No newline at end of file diff --git a/root/usr/share/openclaw/ui/lib/xterm.min.css b/root/usr/share/openclaw/ui/lib/xterm.min.css new file mode 100644 index 0000000..aced1fa --- /dev/null +++ b/root/usr/share/openclaw/ui/lib/xterm.min.css @@ -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 */ \ No newline at end of file diff --git a/root/usr/share/openclaw/ui/lib/xterm.min.js b/root/usr/share/openclaw/ui/lib/xterm.min.js new file mode 100644 index 0000000..0a51bfb --- /dev/null +++ b/root/usr/share/openclaw/ui/lib/xterm.min.js @@ -0,0 +1,8 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/@xterm/xterm@5.5.0/lib/xterm.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var i=t();for(var s in i)("object"==typeof exports?exports:e)[s]=i[s]}}(globalThis,(()=>(()=>{"use strict";var e={4567:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.AccessibilityManager=void 0;const n=i(9042),o=i(9924),a=i(844),h=i(4725),c=i(2585),l=i(3656);let d=t.AccessibilityManager=class extends a.Disposable{constructor(e,t,i,s){super(),this._terminal=e,this._coreBrowserService=i,this._renderService=s,this._rowColumns=new WeakMap,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=this._coreBrowserService.mainDocument.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=this._coreBrowserService.mainDocument.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let e=0;ethis._handleBoundaryFocus(e,0),this._bottomBoundaryFocusListener=e=>this._handleBoundaryFocus(e,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=this._coreBrowserService.mainDocument.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new o.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((e=>this._handleResize(e.rows)))),this.register(this._terminal.onRender((e=>this._refreshRows(e.start,e.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((e=>this._handleChar(e)))),this.register(this._terminal.onLineFeed((()=>this._handleChar("\n")))),this.register(this._terminal.onA11yTab((e=>this._handleTab(e)))),this.register(this._terminal.onKey((e=>this._handleKey(e.key)))),this.register(this._terminal.onBlur((()=>this._clearLiveRegion()))),this.register(this._renderService.onDimensionsChange((()=>this._refreshRowsDimensions()))),this.register((0,l.addDisposableDomListener)(document,"selectionchange",(()=>this._handleSelectionChange()))),this.register(this._coreBrowserService.onDprChange((()=>this._refreshRowsDimensions()))),this._refreshRows(),this.register((0,a.toDisposable)((()=>{this._accessibilityContainer.remove(),this._rowElements.length=0})))}_handleTab(e){for(let t=0;t0?this._charsToConsume.shift()!==e&&(this._charsToAnnounce+=e):this._charsToAnnounce+=e,"\n"===e&&(this._liveRegionLineCount++,21===this._liveRegionLineCount&&(this._liveRegion.textContent+=n.tooMuchOutput)))}_clearLiveRegion(){this._liveRegion.textContent="",this._liveRegionLineCount=0}_handleKey(e){this._clearLiveRegion(),/\p{Control}/u.test(e)||this._charsToConsume.push(e)}_refreshRows(e,t){this._liveRegionDebouncer.refresh(e,t,this._terminal.rows)}_renderRows(e,t){const i=this._terminal.buffer,s=i.lines.length.toString();for(let r=e;r<=t;r++){const e=i.lines.get(i.ydisp+r),t=[],n=e?.translateToString(!0,void 0,void 0,t)||"",o=(i.ydisp+r+1).toString(),a=this._rowElements[r];a&&(0===n.length?(a.innerText=" ",this._rowColumns.set(a,[0,1])):(a.textContent=n,this._rowColumns.set(a,t)),a.setAttribute("aria-posinset",o),a.setAttribute("aria-setsize",s))}this._announceCharacters()}_announceCharacters(){0!==this._charsToAnnounce.length&&(this._liveRegion.textContent+=this._charsToAnnounce,this._charsToAnnounce="")}_handleBoundaryFocus(e,t){const i=e.target,s=this._rowElements[0===t?1:this._rowElements.length-2];if(i.getAttribute("aria-posinset")===(0===t?"1":`${this._terminal.buffer.lines.length}`))return;if(e.relatedTarget!==s)return;let r,n;if(0===t?(r=i,n=this._rowElements.pop(),this._rowContainer.removeChild(n)):(r=this._rowElements.shift(),n=i,this._rowContainer.removeChild(r)),r.removeEventListener("focus",this._topBoundaryFocusListener),n.removeEventListener("focus",this._bottomBoundaryFocusListener),0===t){const e=this._createAccessibilityTreeNode();this._rowElements.unshift(e),this._rowContainer.insertAdjacentElement("afterbegin",e)}else{const e=this._createAccessibilityTreeNode();this._rowElements.push(e),this._rowContainer.appendChild(e)}this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._terminal.scrollLines(0===t?-1:1),this._rowElements[0===t?1:this._rowElements.length-2].focus(),e.preventDefault(),e.stopImmediatePropagation()}_handleSelectionChange(){if(0===this._rowElements.length)return;const e=document.getSelection();if(!e)return;if(e.isCollapsed)return void(this._rowContainer.contains(e.anchorNode)&&this._terminal.clearSelection());if(!e.anchorNode||!e.focusNode)return void console.error("anchorNode and/or focusNode are null");let t={node:e.anchorNode,offset:e.anchorOffset},i={node:e.focusNode,offset:e.focusOffset};if((t.node.compareDocumentPosition(i.node)&Node.DOCUMENT_POSITION_PRECEDING||t.node===i.node&&t.offset>i.offset)&&([t,i]=[i,t]),t.node.compareDocumentPosition(this._rowElements[0])&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_FOLLOWING)&&(t={node:this._rowElements[0].childNodes[0],offset:0}),!this._rowContainer.contains(t.node))return;const s=this._rowElements.slice(-1)[0];if(i.node.compareDocumentPosition(s)&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_PRECEDING)&&(i={node:s,offset:s.textContent?.length??0}),!this._rowContainer.contains(i.node))return;const r=({node:e,offset:t})=>{const i=e instanceof Text?e.parentNode:e;let s=parseInt(i?.getAttribute("aria-posinset"),10)-1;if(isNaN(s))return console.warn("row is invalid. Race condition?"),null;const r=this._rowColumns.get(i);if(!r)return console.warn("columns is null. Race condition?"),null;let n=t=this._terminal.cols&&(++s,n=0),{row:s,column:n}},n=r(t),o=r(i);if(n&&o){if(n.row>o.row||n.row===o.row&&n.column>=o.column)throw new Error("invalid range");this._terminal.select(n.column,n.row,(o.row-n.row)*this._terminal.cols-n.column+o.column)}}_handleResize(e){this._rowElements[this._rowElements.length-1].removeEventListener("focus",this._bottomBoundaryFocusListener);for(let e=this._rowContainer.children.length;ee;)this._rowContainer.removeChild(this._rowElements.pop());this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions()}_createAccessibilityTreeNode(){const e=this._coreBrowserService.mainDocument.createElement("div");return e.setAttribute("role","listitem"),e.tabIndex=-1,this._refreshRowDimensions(e),e}_refreshRowsDimensions(){if(this._renderService.dimensions.css.cell.height){this._accessibilityContainer.style.width=`${this._renderService.dimensions.css.canvas.width}px`,this._rowElements.length!==this._terminal.rows&&this._handleResize(this._terminal.rows);for(let e=0;e{function i(e){return e.replace(/\r?\n/g,"\r")}function s(e,t){return t?"[200~"+e+"[201~":e}function r(e,t,r,n){e=s(e=i(e),r.decPrivateModes.bracketedPasteMode&&!0!==n.rawOptions.ignoreBracketedPasteMode),r.triggerDataEvent(e,!0),t.value=""}function n(e,t,i){const s=i.getBoundingClientRect(),r=e.clientX-s.left-10,n=e.clientY-s.top-10;t.style.width="20px",t.style.height="20px",t.style.left=`${r}px`,t.style.top=`${n}px`,t.style.zIndex="1000",t.focus()}Object.defineProperty(t,"__esModule",{value:!0}),t.rightClickHandler=t.moveTextAreaUnderMouseCursor=t.paste=t.handlePasteEvent=t.copyHandler=t.bracketTextForPaste=t.prepareTextForTerminal=void 0,t.prepareTextForTerminal=i,t.bracketTextForPaste=s,t.copyHandler=function(e,t){e.clipboardData&&e.clipboardData.setData("text/plain",t.selectionText),e.preventDefault()},t.handlePasteEvent=function(e,t,i,s){e.stopPropagation(),e.clipboardData&&r(e.clipboardData.getData("text/plain"),t,i,s)},t.paste=r,t.moveTextAreaUnderMouseCursor=n,t.rightClickHandler=function(e,t,i,s,r){n(e,t,i),r&&s.rightClickSelect(e),t.value=s.selectionText,t.select()}},7239:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ColorContrastCache=void 0;const s=i(1505);t.ColorContrastCache=class{constructor(){this._color=new s.TwoKeyMap,this._css=new s.TwoKeyMap}setCss(e,t,i){this._css.set(e,t,i)}getCss(e,t){return this._css.get(e,t)}setColor(e,t,i){this._color.set(e,t,i)}getColor(e,t){return this._color.get(e,t)}clear(){this._color.clear(),this._css.clear()}}},3656:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.addDisposableDomListener=void 0,t.addDisposableDomListener=function(e,t,i,s){e.addEventListener(t,i,s);let r=!1;return{dispose:()=>{r||(r=!0,e.removeEventListener(t,i,s))}}}},3551:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.Linkifier=void 0;const n=i(3656),o=i(8460),a=i(844),h=i(2585),c=i(4725);let l=t.Linkifier=class extends a.Disposable{get currentLink(){return this._currentLink}constructor(e,t,i,s,r){super(),this._element=e,this._mouseService=t,this._renderService=i,this._bufferService=s,this._linkProviderService=r,this._linkCacheDisposables=[],this._isMouseOut=!0,this._wasResized=!1,this._activeLine=-1,this._onShowLinkUnderline=this.register(new o.EventEmitter),this.onShowLinkUnderline=this._onShowLinkUnderline.event,this._onHideLinkUnderline=this.register(new o.EventEmitter),this.onHideLinkUnderline=this._onHideLinkUnderline.event,this.register((0,a.getDisposeArrayDisposable)(this._linkCacheDisposables)),this.register((0,a.toDisposable)((()=>{this._lastMouseEvent=void 0,this._activeProviderReplies?.clear()}))),this.register(this._bufferService.onResize((()=>{this._clearCurrentLink(),this._wasResized=!0}))),this.register((0,n.addDisposableDomListener)(this._element,"mouseleave",(()=>{this._isMouseOut=!0,this._clearCurrentLink()}))),this.register((0,n.addDisposableDomListener)(this._element,"mousemove",this._handleMouseMove.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mousedown",this._handleMouseDown.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mouseup",this._handleMouseUp.bind(this)))}_handleMouseMove(e){this._lastMouseEvent=e;const t=this._positionFromMouseEvent(e,this._element,this._mouseService);if(!t)return;this._isMouseOut=!1;const i=e.composedPath();for(let e=0;e{e?.forEach((e=>{e.link.dispose&&e.link.dispose()}))})),this._activeProviderReplies=new Map,this._activeLine=e.y);let i=!1;for(const[s,r]of this._linkProviderService.linkProviders.entries())if(t){const t=this._activeProviderReplies?.get(s);t&&(i=this._checkLinkProviderResult(s,e,i))}else r.provideLinks(e.y,(t=>{if(this._isMouseOut)return;const r=t?.map((e=>({link:e})));this._activeProviderReplies?.set(s,r),i=this._checkLinkProviderResult(s,e,i),this._activeProviderReplies?.size===this._linkProviderService.linkProviders.length&&this._removeIntersectingLinks(e.y,this._activeProviderReplies)}))}_removeIntersectingLinks(e,t){const i=new Set;for(let s=0;se?this._bufferService.cols:s.link.range.end.x;for(let e=n;e<=o;e++){if(i.has(e)){r.splice(t--,1);break}i.add(e)}}}}_checkLinkProviderResult(e,t,i){if(!this._activeProviderReplies)return i;const s=this._activeProviderReplies.get(e);let r=!1;for(let t=0;tthis._linkAtPosition(e.link,t)));e&&(i=!0,this._handleNewLink(e))}if(this._activeProviderReplies.size===this._linkProviderService.linkProviders.length&&!i)for(let e=0;ethis._linkAtPosition(e.link,t)));if(s){i=!0,this._handleNewLink(s);break}}return i}_handleMouseDown(){this._mouseDownLink=this._currentLink}_handleMouseUp(e){if(!this._currentLink)return;const t=this._positionFromMouseEvent(e,this._element,this._mouseService);t&&this._mouseDownLink===this._currentLink&&this._linkAtPosition(this._currentLink.link,t)&&this._currentLink.link.activate(e,this._currentLink.link.text)}_clearCurrentLink(e,t){this._currentLink&&this._lastMouseEvent&&(!e||!t||this._currentLink.link.range.start.y>=e&&this._currentLink.link.range.end.y<=t)&&(this._linkLeave(this._element,this._currentLink.link,this._lastMouseEvent),this._currentLink=void 0,(0,a.disposeArray)(this._linkCacheDisposables))}_handleNewLink(e){if(!this._lastMouseEvent)return;const t=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);t&&this._linkAtPosition(e.link,t)&&(this._currentLink=e,this._currentLink.state={decorations:{underline:void 0===e.link.decorations||e.link.decorations.underline,pointerCursor:void 0===e.link.decorations||e.link.decorations.pointerCursor},isHovered:!0},this._linkHover(this._element,e.link,this._lastMouseEvent),e.link.decorations={},Object.defineProperties(e.link.decorations,{pointerCursor:{get:()=>this._currentLink?.state?.decorations.pointerCursor,set:e=>{this._currentLink?.state&&this._currentLink.state.decorations.pointerCursor!==e&&(this._currentLink.state.decorations.pointerCursor=e,this._currentLink.state.isHovered&&this._element.classList.toggle("xterm-cursor-pointer",e))}},underline:{get:()=>this._currentLink?.state?.decorations.underline,set:t=>{this._currentLink?.state&&this._currentLink?.state?.decorations.underline!==t&&(this._currentLink.state.decorations.underline=t,this._currentLink.state.isHovered&&this._fireUnderlineEvent(e.link,t))}}}),this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange((e=>{if(!this._currentLink)return;const t=0===e.start?0:e.start+1+this._bufferService.buffer.ydisp,i=this._bufferService.buffer.ydisp+1+e.end;if(this._currentLink.link.range.start.y>=t&&this._currentLink.link.range.end.y<=i&&(this._clearCurrentLink(t,i),this._lastMouseEvent)){const e=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);e&&this._askForLink(e,!1)}}))))}_linkHover(e,t,i){this._currentLink?.state&&(this._currentLink.state.isHovered=!0,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(t,!0),this._currentLink.state.decorations.pointerCursor&&e.classList.add("xterm-cursor-pointer")),t.hover&&t.hover(i,t.text)}_fireUnderlineEvent(e,t){const i=e.range,s=this._bufferService.buffer.ydisp,r=this._createLinkUnderlineEvent(i.start.x-1,i.start.y-s-1,i.end.x,i.end.y-s-1,void 0);(t?this._onShowLinkUnderline:this._onHideLinkUnderline).fire(r)}_linkLeave(e,t,i){this._currentLink?.state&&(this._currentLink.state.isHovered=!1,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(t,!1),this._currentLink.state.decorations.pointerCursor&&e.classList.remove("xterm-cursor-pointer")),t.leave&&t.leave(i,t.text)}_linkAtPosition(e,t){const i=e.range.start.y*this._bufferService.cols+e.range.start.x,s=e.range.end.y*this._bufferService.cols+e.range.end.x,r=t.y*this._bufferService.cols+t.x;return i<=r&&r<=s}_positionFromMouseEvent(e,t,i){const s=i.getCoords(e,t,this._bufferService.cols,this._bufferService.rows);if(s)return{x:s[0],y:s[1]+this._bufferService.buffer.ydisp}}_createLinkUnderlineEvent(e,t,i,s,r){return{x1:e,y1:t,x2:i,y2:s,cols:this._bufferService.cols,fg:r}}};t.Linkifier=l=s([r(1,c.IMouseService),r(2,c.IRenderService),r(3,h.IBufferService),r(4,c.ILinkProviderService)],l)},9042:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.tooMuchOutput=t.promptLabel=void 0,t.promptLabel="Terminal input",t.tooMuchOutput="Too much output to announce, navigate to rows manually to read"},3730:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OscLinkProvider=void 0;const n=i(511),o=i(2585);let a=t.OscLinkProvider=class{constructor(e,t,i){this._bufferService=e,this._optionsService=t,this._oscLinkService=i}provideLinks(e,t){const i=this._bufferService.buffer.lines.get(e-1);if(!i)return void t(void 0);const s=[],r=this._optionsService.rawOptions.linkHandler,o=new n.CellData,a=i.getTrimmedLength();let c=-1,l=-1,d=!1;for(let t=0;tr?r.activate(e,t,n):h(0,t),hover:(e,t)=>r?.hover?.(e,t,n),leave:(e,t)=>r?.leave?.(e,t,n)})}d=!1,o.hasExtendedAttrs()&&o.extended.urlId?(l=t,c=o.extended.urlId):(l=-1,c=-1)}}t(s)}};function h(e,t){if(confirm(`Do you want to navigate to ${t}?\n\nWARNING: This link could potentially be dangerous`)){const e=window.open();if(e){try{e.opener=null}catch{}e.location.href=t}else console.warn("Opening link blocked as opener could not be cleared")}}t.OscLinkProvider=a=s([r(0,o.IBufferService),r(1,o.IOptionsService),r(2,o.IOscLinkService)],a)},6193:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.RenderDebouncer=void 0,t.RenderDebouncer=class{constructor(e,t){this._renderCallback=e,this._coreBrowserService=t,this._refreshCallbacks=[]}dispose(){this._animationFrame&&(this._coreBrowserService.window.cancelAnimationFrame(this._animationFrame),this._animationFrame=void 0)}addRefreshCallback(e){return this._refreshCallbacks.push(e),this._animationFrame||(this._animationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._innerRefresh()))),this._animationFrame}refresh(e,t,i){this._rowCount=i,e=void 0!==e?e:0,t=void 0!==t?t:this._rowCount-1,this._rowStart=void 0!==this._rowStart?Math.min(this._rowStart,e):e,this._rowEnd=void 0!==this._rowEnd?Math.max(this._rowEnd,t):t,this._animationFrame||(this._animationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._innerRefresh())))}_innerRefresh(){if(this._animationFrame=void 0,void 0===this._rowStart||void 0===this._rowEnd||void 0===this._rowCount)return void this._runRefreshCallbacks();const e=Math.max(this._rowStart,0),t=Math.min(this._rowEnd,this._rowCount-1);this._rowStart=void 0,this._rowEnd=void 0,this._renderCallback(e,t),this._runRefreshCallbacks()}_runRefreshCallbacks(){for(const e of this._refreshCallbacks)e(0);this._refreshCallbacks=[]}}},3236:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Terminal=void 0;const s=i(3614),r=i(3656),n=i(3551),o=i(9042),a=i(3730),h=i(1680),c=i(3107),l=i(5744),d=i(2950),_=i(1296),u=i(428),f=i(4269),v=i(5114),p=i(8934),g=i(3230),m=i(9312),S=i(4725),C=i(6731),b=i(8055),w=i(8969),y=i(8460),E=i(844),k=i(6114),L=i(8437),D=i(2584),R=i(7399),x=i(5941),A=i(9074),B=i(2585),T=i(5435),M=i(4567),O=i(779);class P extends w.CoreTerminal{get onFocus(){return this._onFocus.event}get onBlur(){return this._onBlur.event}get onA11yChar(){return this._onA11yCharEmitter.event}get onA11yTab(){return this._onA11yTabEmitter.event}get onWillOpen(){return this._onWillOpen.event}constructor(e={}){super(e),this.browser=k,this._keyDownHandled=!1,this._keyDownSeen=!1,this._keyPressHandled=!1,this._unprocessedDeadKey=!1,this._accessibilityManager=this.register(new E.MutableDisposable),this._onCursorMove=this.register(new y.EventEmitter),this.onCursorMove=this._onCursorMove.event,this._onKey=this.register(new y.EventEmitter),this.onKey=this._onKey.event,this._onRender=this.register(new y.EventEmitter),this.onRender=this._onRender.event,this._onSelectionChange=this.register(new y.EventEmitter),this.onSelectionChange=this._onSelectionChange.event,this._onTitleChange=this.register(new y.EventEmitter),this.onTitleChange=this._onTitleChange.event,this._onBell=this.register(new y.EventEmitter),this.onBell=this._onBell.event,this._onFocus=this.register(new y.EventEmitter),this._onBlur=this.register(new y.EventEmitter),this._onA11yCharEmitter=this.register(new y.EventEmitter),this._onA11yTabEmitter=this.register(new y.EventEmitter),this._onWillOpen=this.register(new y.EventEmitter),this._setup(),this._decorationService=this._instantiationService.createInstance(A.DecorationService),this._instantiationService.setService(B.IDecorationService,this._decorationService),this._linkProviderService=this._instantiationService.createInstance(O.LinkProviderService),this._instantiationService.setService(S.ILinkProviderService,this._linkProviderService),this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(a.OscLinkProvider)),this.register(this._inputHandler.onRequestBell((()=>this._onBell.fire()))),this.register(this._inputHandler.onRequestRefreshRows(((e,t)=>this.refresh(e,t)))),this.register(this._inputHandler.onRequestSendFocus((()=>this._reportFocus()))),this.register(this._inputHandler.onRequestReset((()=>this.reset()))),this.register(this._inputHandler.onRequestWindowsOptionsReport((e=>this._reportWindowsOptions(e)))),this.register(this._inputHandler.onColor((e=>this._handleColorEvent(e)))),this.register((0,y.forwardEvent)(this._inputHandler.onCursorMove,this._onCursorMove)),this.register((0,y.forwardEvent)(this._inputHandler.onTitleChange,this._onTitleChange)),this.register((0,y.forwardEvent)(this._inputHandler.onA11yChar,this._onA11yCharEmitter)),this.register((0,y.forwardEvent)(this._inputHandler.onA11yTab,this._onA11yTabEmitter)),this.register(this._bufferService.onResize((e=>this._afterResize(e.cols,e.rows)))),this.register((0,E.toDisposable)((()=>{this._customKeyEventHandler=void 0,this.element?.parentNode?.removeChild(this.element)})))}_handleColorEvent(e){if(this._themeService)for(const t of e){let e,i="";switch(t.index){case 256:e="foreground",i="10";break;case 257:e="background",i="11";break;case 258:e="cursor",i="12";break;default:e="ansi",i="4;"+t.index}switch(t.type){case 0:const s=b.color.toColorRGB("ansi"===e?this._themeService.colors.ansi[t.index]:this._themeService.colors[e]);this.coreService.triggerDataEvent(`${D.C0.ESC}]${i};${(0,x.toRgbString)(s)}${D.C1_ESCAPED.ST}`);break;case 1:if("ansi"===e)this._themeService.modifyColors((e=>e.ansi[t.index]=b.channels.toColor(...t.color)));else{const i=e;this._themeService.modifyColors((e=>e[i]=b.channels.toColor(...t.color)))}break;case 2:this._themeService.restoreColor(t.index)}}}_setup(){super._setup(),this._customKeyEventHandler=void 0}get buffer(){return this.buffers.active}focus(){this.textarea&&this.textarea.focus({preventScroll:!0})}_handleScreenReaderModeOptionChange(e){e?!this._accessibilityManager.value&&this._renderService&&(this._accessibilityManager.value=this._instantiationService.createInstance(M.AccessibilityManager,this)):this._accessibilityManager.clear()}_handleTextAreaFocus(e){this.coreService.decPrivateModes.sendFocus&&this.coreService.triggerDataEvent(D.C0.ESC+"[I"),this.element.classList.add("focus"),this._showCursor(),this._onFocus.fire()}blur(){return this.textarea?.blur()}_handleTextAreaBlur(){this.textarea.value="",this.refresh(this.buffer.y,this.buffer.y),this.coreService.decPrivateModes.sendFocus&&this.coreService.triggerDataEvent(D.C0.ESC+"[O"),this.element.classList.remove("focus"),this._onBlur.fire()}_syncTextArea(){if(!this.textarea||!this.buffer.isCursorInViewport||this._compositionHelper.isComposing||!this._renderService)return;const e=this.buffer.ybase+this.buffer.y,t=this.buffer.lines.get(e);if(!t)return;const i=Math.min(this.buffer.x,this.cols-1),s=this._renderService.dimensions.css.cell.height,r=t.getWidth(i),n=this._renderService.dimensions.css.cell.width*r,o=this.buffer.y*this._renderService.dimensions.css.cell.height,a=i*this._renderService.dimensions.css.cell.width;this.textarea.style.left=a+"px",this.textarea.style.top=o+"px",this.textarea.style.width=n+"px",this.textarea.style.height=s+"px",this.textarea.style.lineHeight=s+"px",this.textarea.style.zIndex="-5"}_initGlobal(){this._bindKeys(),this.register((0,r.addDisposableDomListener)(this.element,"copy",(e=>{this.hasSelection()&&(0,s.copyHandler)(e,this._selectionService)})));const e=e=>(0,s.handlePasteEvent)(e,this.textarea,this.coreService,this.optionsService);this.register((0,r.addDisposableDomListener)(this.textarea,"paste",e)),this.register((0,r.addDisposableDomListener)(this.element,"paste",e)),k.isFirefox?this.register((0,r.addDisposableDomListener)(this.element,"mousedown",(e=>{2===e.button&&(0,s.rightClickHandler)(e,this.textarea,this.screenElement,this._selectionService,this.options.rightClickSelectsWord)}))):this.register((0,r.addDisposableDomListener)(this.element,"contextmenu",(e=>{(0,s.rightClickHandler)(e,this.textarea,this.screenElement,this._selectionService,this.options.rightClickSelectsWord)}))),k.isLinux&&this.register((0,r.addDisposableDomListener)(this.element,"auxclick",(e=>{1===e.button&&(0,s.moveTextAreaUnderMouseCursor)(e,this.textarea,this.screenElement)})))}_bindKeys(){this.register((0,r.addDisposableDomListener)(this.textarea,"keyup",(e=>this._keyUp(e)),!0)),this.register((0,r.addDisposableDomListener)(this.textarea,"keydown",(e=>this._keyDown(e)),!0)),this.register((0,r.addDisposableDomListener)(this.textarea,"keypress",(e=>this._keyPress(e)),!0)),this.register((0,r.addDisposableDomListener)(this.textarea,"compositionstart",(()=>this._compositionHelper.compositionstart()))),this.register((0,r.addDisposableDomListener)(this.textarea,"compositionupdate",(e=>this._compositionHelper.compositionupdate(e)))),this.register((0,r.addDisposableDomListener)(this.textarea,"compositionend",(()=>this._compositionHelper.compositionend()))),this.register((0,r.addDisposableDomListener)(this.textarea,"input",(e=>this._inputEvent(e)),!0)),this.register(this.onRender((()=>this._compositionHelper.updateCompositionElements())))}open(e){if(!e)throw new Error("Terminal requires a parent element.");if(e.isConnected||this._logService.debug("Terminal.open was called on an element that was not attached to the DOM"),this.element?.ownerDocument.defaultView&&this._coreBrowserService)return void(this.element.ownerDocument.defaultView!==this._coreBrowserService.window&&(this._coreBrowserService.window=this.element.ownerDocument.defaultView));this._document=e.ownerDocument,this.options.documentOverride&&this.options.documentOverride instanceof Document&&(this._document=this.optionsService.rawOptions.documentOverride),this.element=this._document.createElement("div"),this.element.dir="ltr",this.element.classList.add("terminal"),this.element.classList.add("xterm"),e.appendChild(this.element);const t=this._document.createDocumentFragment();this._viewportElement=this._document.createElement("div"),this._viewportElement.classList.add("xterm-viewport"),t.appendChild(this._viewportElement),this._viewportScrollArea=this._document.createElement("div"),this._viewportScrollArea.classList.add("xterm-scroll-area"),this._viewportElement.appendChild(this._viewportScrollArea),this.screenElement=this._document.createElement("div"),this.screenElement.classList.add("xterm-screen"),this.register((0,r.addDisposableDomListener)(this.screenElement,"mousemove",(e=>this.updateCursorStyle(e)))),this._helperContainer=this._document.createElement("div"),this._helperContainer.classList.add("xterm-helpers"),this.screenElement.appendChild(this._helperContainer),t.appendChild(this.screenElement),this.textarea=this._document.createElement("textarea"),this.textarea.classList.add("xterm-helper-textarea"),this.textarea.setAttribute("aria-label",o.promptLabel),k.isChromeOS||this.textarea.setAttribute("aria-multiline","false"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.tabIndex=0,this._coreBrowserService=this.register(this._instantiationService.createInstance(v.CoreBrowserService,this.textarea,e.ownerDocument.defaultView??window,this._document??"undefined"!=typeof window?window.document:null)),this._instantiationService.setService(S.ICoreBrowserService,this._coreBrowserService),this.register((0,r.addDisposableDomListener)(this.textarea,"focus",(e=>this._handleTextAreaFocus(e)))),this.register((0,r.addDisposableDomListener)(this.textarea,"blur",(()=>this._handleTextAreaBlur()))),this._helperContainer.appendChild(this.textarea),this._charSizeService=this._instantiationService.createInstance(u.CharSizeService,this._document,this._helperContainer),this._instantiationService.setService(S.ICharSizeService,this._charSizeService),this._themeService=this._instantiationService.createInstance(C.ThemeService),this._instantiationService.setService(S.IThemeService,this._themeService),this._characterJoinerService=this._instantiationService.createInstance(f.CharacterJoinerService),this._instantiationService.setService(S.ICharacterJoinerService,this._characterJoinerService),this._renderService=this.register(this._instantiationService.createInstance(g.RenderService,this.rows,this.screenElement)),this._instantiationService.setService(S.IRenderService,this._renderService),this.register(this._renderService.onRenderedViewportChange((e=>this._onRender.fire(e)))),this.onResize((e=>this._renderService.resize(e.cols,e.rows))),this._compositionView=this._document.createElement("div"),this._compositionView.classList.add("composition-view"),this._compositionHelper=this._instantiationService.createInstance(d.CompositionHelper,this.textarea,this._compositionView),this._helperContainer.appendChild(this._compositionView),this._mouseService=this._instantiationService.createInstance(p.MouseService),this._instantiationService.setService(S.IMouseService,this._mouseService),this.linkifier=this.register(this._instantiationService.createInstance(n.Linkifier,this.screenElement)),this.element.appendChild(t);try{this._onWillOpen.fire(this.element)}catch{}this._renderService.hasRenderer()||this._renderService.setRenderer(this._createRenderer()),this.viewport=this._instantiationService.createInstance(h.Viewport,this._viewportElement,this._viewportScrollArea),this.viewport.onRequestScrollLines((e=>this.scrollLines(e.amount,e.suppressScrollEvent,1))),this.register(this._inputHandler.onRequestSyncScrollBar((()=>this.viewport.syncScrollArea()))),this.register(this.viewport),this.register(this.onCursorMove((()=>{this._renderService.handleCursorMove(),this._syncTextArea()}))),this.register(this.onResize((()=>this._renderService.handleResize(this.cols,this.rows)))),this.register(this.onBlur((()=>this._renderService.handleBlur()))),this.register(this.onFocus((()=>this._renderService.handleFocus()))),this.register(this._renderService.onDimensionsChange((()=>this.viewport.syncScrollArea()))),this._selectionService=this.register(this._instantiationService.createInstance(m.SelectionService,this.element,this.screenElement,this.linkifier)),this._instantiationService.setService(S.ISelectionService,this._selectionService),this.register(this._selectionService.onRequestScrollLines((e=>this.scrollLines(e.amount,e.suppressScrollEvent)))),this.register(this._selectionService.onSelectionChange((()=>this._onSelectionChange.fire()))),this.register(this._selectionService.onRequestRedraw((e=>this._renderService.handleSelectionChanged(e.start,e.end,e.columnSelectMode)))),this.register(this._selectionService.onLinuxMouseSelection((e=>{this.textarea.value=e,this.textarea.focus(),this.textarea.select()}))),this.register(this._onScroll.event((e=>{this.viewport.syncScrollArea(),this._selectionService.refresh()}))),this.register((0,r.addDisposableDomListener)(this._viewportElement,"scroll",(()=>this._selectionService.refresh()))),this.register(this._instantiationService.createInstance(c.BufferDecorationRenderer,this.screenElement)),this.register((0,r.addDisposableDomListener)(this.element,"mousedown",(e=>this._selectionService.handleMouseDown(e)))),this.coreMouseService.areMouseEventsActive?(this._selectionService.disable(),this.element.classList.add("enable-mouse-events")):this._selectionService.enable(),this.options.screenReaderMode&&(this._accessibilityManager.value=this._instantiationService.createInstance(M.AccessibilityManager,this)),this.register(this.optionsService.onSpecificOptionChange("screenReaderMode",(e=>this._handleScreenReaderModeOptionChange(e)))),this.options.overviewRulerWidth&&(this._overviewRulerRenderer=this.register(this._instantiationService.createInstance(l.OverviewRulerRenderer,this._viewportElement,this.screenElement))),this.optionsService.onSpecificOptionChange("overviewRulerWidth",(e=>{!this._overviewRulerRenderer&&e&&this._viewportElement&&this.screenElement&&(this._overviewRulerRenderer=this.register(this._instantiationService.createInstance(l.OverviewRulerRenderer,this._viewportElement,this.screenElement)))})),this._charSizeService.measure(),this.refresh(0,this.rows-1),this._initGlobal(),this.bindMouse()}_createRenderer(){return this._instantiationService.createInstance(_.DomRenderer,this,this._document,this.element,this.screenElement,this._viewportElement,this._helperContainer,this.linkifier)}bindMouse(){const e=this,t=this.element;function i(t){const i=e._mouseService.getMouseReportCoords(t,e.screenElement);if(!i)return!1;let s,r;switch(t.overrideType||t.type){case"mousemove":r=32,void 0===t.buttons?(s=3,void 0!==t.button&&(s=t.button<3?t.button:3)):s=1&t.buttons?0:4&t.buttons?1:2&t.buttons?2:3;break;case"mouseup":r=0,s=t.button<3?t.button:3;break;case"mousedown":r=1,s=t.button<3?t.button:3;break;case"wheel":if(e._customWheelEventHandler&&!1===e._customWheelEventHandler(t))return!1;if(0===e.viewport.getLinesScrolled(t))return!1;r=t.deltaY<0?0:1,s=4;break;default:return!1}return!(void 0===r||void 0===s||s>4)&&e.coreMouseService.triggerMouseEvent({col:i.col,row:i.row,x:i.x,y:i.y,button:s,action:r,ctrl:t.ctrlKey,alt:t.altKey,shift:t.shiftKey})}const s={mouseup:null,wheel:null,mousedrag:null,mousemove:null},n={mouseup:e=>(i(e),e.buttons||(this._document.removeEventListener("mouseup",s.mouseup),s.mousedrag&&this._document.removeEventListener("mousemove",s.mousedrag)),this.cancel(e)),wheel:e=>(i(e),this.cancel(e,!0)),mousedrag:e=>{e.buttons&&i(e)},mousemove:e=>{e.buttons||i(e)}};this.register(this.coreMouseService.onProtocolChange((e=>{e?("debug"===this.optionsService.rawOptions.logLevel&&this._logService.debug("Binding to mouse events:",this.coreMouseService.explainEvents(e)),this.element.classList.add("enable-mouse-events"),this._selectionService.disable()):(this._logService.debug("Unbinding from mouse events."),this.element.classList.remove("enable-mouse-events"),this._selectionService.enable()),8&e?s.mousemove||(t.addEventListener("mousemove",n.mousemove),s.mousemove=n.mousemove):(t.removeEventListener("mousemove",s.mousemove),s.mousemove=null),16&e?s.wheel||(t.addEventListener("wheel",n.wheel,{passive:!1}),s.wheel=n.wheel):(t.removeEventListener("wheel",s.wheel),s.wheel=null),2&e?s.mouseup||(s.mouseup=n.mouseup):(this._document.removeEventListener("mouseup",s.mouseup),s.mouseup=null),4&e?s.mousedrag||(s.mousedrag=n.mousedrag):(this._document.removeEventListener("mousemove",s.mousedrag),s.mousedrag=null)}))),this.coreMouseService.activeProtocol=this.coreMouseService.activeProtocol,this.register((0,r.addDisposableDomListener)(t,"mousedown",(e=>{if(e.preventDefault(),this.focus(),this.coreMouseService.areMouseEventsActive&&!this._selectionService.shouldForceSelection(e))return i(e),s.mouseup&&this._document.addEventListener("mouseup",s.mouseup),s.mousedrag&&this._document.addEventListener("mousemove",s.mousedrag),this.cancel(e)}))),this.register((0,r.addDisposableDomListener)(t,"wheel",(e=>{if(!s.wheel){if(this._customWheelEventHandler&&!1===this._customWheelEventHandler(e))return!1;if(!this.buffer.hasScrollback){const t=this.viewport.getLinesScrolled(e);if(0===t)return;const i=D.C0.ESC+(this.coreService.decPrivateModes.applicationCursorKeys?"O":"[")+(e.deltaY<0?"A":"B");let s="";for(let e=0;e{if(!this.coreMouseService.areMouseEventsActive)return this.viewport.handleTouchStart(e),this.cancel(e)}),{passive:!0})),this.register((0,r.addDisposableDomListener)(t,"touchmove",(e=>{if(!this.coreMouseService.areMouseEventsActive)return this.viewport.handleTouchMove(e)?void 0:this.cancel(e)}),{passive:!1}))}refresh(e,t){this._renderService?.refreshRows(e,t)}updateCursorStyle(e){this._selectionService?.shouldColumnSelect(e)?this.element.classList.add("column-select"):this.element.classList.remove("column-select")}_showCursor(){this.coreService.isCursorInitialized||(this.coreService.isCursorInitialized=!0,this.refresh(this.buffer.y,this.buffer.y))}scrollLines(e,t,i=0){1===i?(super.scrollLines(e,t,i),this.refresh(0,this.rows-1)):this.viewport?.scrollLines(e)}paste(e){(0,s.paste)(e,this.textarea,this.coreService,this.optionsService)}attachCustomKeyEventHandler(e){this._customKeyEventHandler=e}attachCustomWheelEventHandler(e){this._customWheelEventHandler=e}registerLinkProvider(e){return this._linkProviderService.registerLinkProvider(e)}registerCharacterJoiner(e){if(!this._characterJoinerService)throw new Error("Terminal must be opened first");const t=this._characterJoinerService.register(e);return this.refresh(0,this.rows-1),t}deregisterCharacterJoiner(e){if(!this._characterJoinerService)throw new Error("Terminal must be opened first");this._characterJoinerService.deregister(e)&&this.refresh(0,this.rows-1)}get markers(){return this.buffer.markers}registerMarker(e){return this.buffer.addMarker(this.buffer.ybase+this.buffer.y+e)}registerDecoration(e){return this._decorationService.registerDecoration(e)}hasSelection(){return!!this._selectionService&&this._selectionService.hasSelection}select(e,t,i){this._selectionService.setSelection(e,t,i)}getSelection(){return this._selectionService?this._selectionService.selectionText:""}getSelectionPosition(){if(this._selectionService&&this._selectionService.hasSelection)return{start:{x:this._selectionService.selectionStart[0],y:this._selectionService.selectionStart[1]},end:{x:this._selectionService.selectionEnd[0],y:this._selectionService.selectionEnd[1]}}}clearSelection(){this._selectionService?.clearSelection()}selectAll(){this._selectionService?.selectAll()}selectLines(e,t){this._selectionService?.selectLines(e,t)}_keyDown(e){if(this._keyDownHandled=!1,this._keyDownSeen=!0,this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;const t=this.browser.isMac&&this.options.macOptionIsMeta&&e.altKey;if(!t&&!this._compositionHelper.keydown(e))return this.options.scrollOnUserInput&&this.buffer.ybase!==this.buffer.ydisp&&this.scrollToBottom(),!1;t||"Dead"!==e.key&&"AltGraph"!==e.key||(this._unprocessedDeadKey=!0);const i=(0,R.evaluateKeyboardEvent)(e,this.coreService.decPrivateModes.applicationCursorKeys,this.browser.isMac,this.options.macOptionIsMeta);if(this.updateCursorStyle(e),3===i.type||2===i.type){const t=this.rows-1;return this.scrollLines(2===i.type?-t:t),this.cancel(e,!0)}return 1===i.type&&this.selectAll(),!!this._isThirdLevelShift(this.browser,e)||(i.cancel&&this.cancel(e,!0),!i.key||!!(e.key&&!e.ctrlKey&&!e.altKey&&!e.metaKey&&1===e.key.length&&e.key.charCodeAt(0)>=65&&e.key.charCodeAt(0)<=90)||(this._unprocessedDeadKey?(this._unprocessedDeadKey=!1,!0):(i.key!==D.C0.ETX&&i.key!==D.C0.CR||(this.textarea.value=""),this._onKey.fire({key:i.key,domEvent:e}),this._showCursor(),this.coreService.triggerDataEvent(i.key,!0),!this.optionsService.rawOptions.screenReaderMode||e.altKey||e.ctrlKey?this.cancel(e,!0):void(this._keyDownHandled=!0))))}_isThirdLevelShift(e,t){const i=e.isMac&&!this.options.macOptionIsMeta&&t.altKey&&!t.ctrlKey&&!t.metaKey||e.isWindows&&t.altKey&&t.ctrlKey&&!t.metaKey||e.isWindows&&t.getModifierState("AltGraph");return"keypress"===t.type?i:i&&(!t.keyCode||t.keyCode>47)}_keyUp(e){this._keyDownSeen=!1,this._customKeyEventHandler&&!1===this._customKeyEventHandler(e)||(function(e){return 16===e.keyCode||17===e.keyCode||18===e.keyCode}(e)||this.focus(),this.updateCursorStyle(e),this._keyPressHandled=!1)}_keyPress(e){let t;if(this._keyPressHandled=!1,this._keyDownHandled)return!1;if(this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;if(this.cancel(e),e.charCode)t=e.charCode;else if(null===e.which||void 0===e.which)t=e.keyCode;else{if(0===e.which||0===e.charCode)return!1;t=e.which}return!(!t||(e.altKey||e.ctrlKey||e.metaKey)&&!this._isThirdLevelShift(this.browser,e)||(t=String.fromCharCode(t),this._onKey.fire({key:t,domEvent:e}),this._showCursor(),this.coreService.triggerDataEvent(t,!0),this._keyPressHandled=!0,this._unprocessedDeadKey=!1,0))}_inputEvent(e){if(e.data&&"insertText"===e.inputType&&(!e.composed||!this._keyDownSeen)&&!this.optionsService.rawOptions.screenReaderMode){if(this._keyPressHandled)return!1;this._unprocessedDeadKey=!1;const t=e.data;return this.coreService.triggerDataEvent(t,!0),this.cancel(e),!0}return!1}resize(e,t){e!==this.cols||t!==this.rows?super.resize(e,t):this._charSizeService&&!this._charSizeService.hasValidSize&&this._charSizeService.measure()}_afterResize(e,t){this._charSizeService?.measure(),this.viewport?.syncScrollArea(!0)}clear(){if(0!==this.buffer.ybase||0!==this.buffer.y){this.buffer.clearAllMarkers(),this.buffer.lines.set(0,this.buffer.lines.get(this.buffer.ybase+this.buffer.y)),this.buffer.lines.length=1,this.buffer.ydisp=0,this.buffer.ybase=0,this.buffer.y=0;for(let e=1;e{Object.defineProperty(t,"__esModule",{value:!0}),t.TimeBasedDebouncer=void 0,t.TimeBasedDebouncer=class{constructor(e,t=1e3){this._renderCallback=e,this._debounceThresholdMS=t,this._lastRefreshMs=0,this._additionalRefreshRequested=!1}dispose(){this._refreshTimeoutID&&clearTimeout(this._refreshTimeoutID)}refresh(e,t,i){this._rowCount=i,e=void 0!==e?e:0,t=void 0!==t?t:this._rowCount-1,this._rowStart=void 0!==this._rowStart?Math.min(this._rowStart,e):e,this._rowEnd=void 0!==this._rowEnd?Math.max(this._rowEnd,t):t;const s=Date.now();if(s-this._lastRefreshMs>=this._debounceThresholdMS)this._lastRefreshMs=s,this._innerRefresh();else if(!this._additionalRefreshRequested){const e=s-this._lastRefreshMs,t=this._debounceThresholdMS-e;this._additionalRefreshRequested=!0,this._refreshTimeoutID=window.setTimeout((()=>{this._lastRefreshMs=Date.now(),this._innerRefresh(),this._additionalRefreshRequested=!1,this._refreshTimeoutID=void 0}),t)}}_innerRefresh(){if(void 0===this._rowStart||void 0===this._rowEnd||void 0===this._rowCount)return;const e=Math.max(this._rowStart,0),t=Math.min(this._rowEnd,this._rowCount-1);this._rowStart=void 0,this._rowEnd=void 0,this._renderCallback(e,t)}}},1680:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.Viewport=void 0;const n=i(3656),o=i(4725),a=i(8460),h=i(844),c=i(2585);let l=t.Viewport=class extends h.Disposable{constructor(e,t,i,s,r,o,h,c){super(),this._viewportElement=e,this._scrollArea=t,this._bufferService=i,this._optionsService=s,this._charSizeService=r,this._renderService=o,this._coreBrowserService=h,this.scrollBarWidth=0,this._currentRowHeight=0,this._currentDeviceCellHeight=0,this._lastRecordedBufferLength=0,this._lastRecordedViewportHeight=0,this._lastRecordedBufferHeight=0,this._lastTouchY=0,this._lastScrollTop=0,this._wheelPartialScroll=0,this._refreshAnimationFrame=null,this._ignoreNextScrollEvent=!1,this._smoothScrollState={startTime:0,origin:-1,target:-1},this._onRequestScrollLines=this.register(new a.EventEmitter),this.onRequestScrollLines=this._onRequestScrollLines.event,this.scrollBarWidth=this._viewportElement.offsetWidth-this._scrollArea.offsetWidth||15,this.register((0,n.addDisposableDomListener)(this._viewportElement,"scroll",this._handleScroll.bind(this))),this._activeBuffer=this._bufferService.buffer,this.register(this._bufferService.buffers.onBufferActivate((e=>this._activeBuffer=e.activeBuffer))),this._renderDimensions=this._renderService.dimensions,this.register(this._renderService.onDimensionsChange((e=>this._renderDimensions=e))),this._handleThemeChange(c.colors),this.register(c.onChangeColors((e=>this._handleThemeChange(e)))),this.register(this._optionsService.onSpecificOptionChange("scrollback",(()=>this.syncScrollArea()))),setTimeout((()=>this.syncScrollArea()))}_handleThemeChange(e){this._viewportElement.style.backgroundColor=e.background.css}reset(){this._currentRowHeight=0,this._currentDeviceCellHeight=0,this._lastRecordedBufferLength=0,this._lastRecordedViewportHeight=0,this._lastRecordedBufferHeight=0,this._lastTouchY=0,this._lastScrollTop=0,this._coreBrowserService.window.requestAnimationFrame((()=>this.syncScrollArea()))}_refresh(e){if(e)return this._innerRefresh(),void(null!==this._refreshAnimationFrame&&this._coreBrowserService.window.cancelAnimationFrame(this._refreshAnimationFrame));null===this._refreshAnimationFrame&&(this._refreshAnimationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._innerRefresh())))}_innerRefresh(){if(this._charSizeService.height>0){this._currentRowHeight=this._renderDimensions.device.cell.height/this._coreBrowserService.dpr,this._currentDeviceCellHeight=this._renderDimensions.device.cell.height,this._lastRecordedViewportHeight=this._viewportElement.offsetHeight;const e=Math.round(this._currentRowHeight*this._lastRecordedBufferLength)+(this._lastRecordedViewportHeight-this._renderDimensions.css.canvas.height);this._lastRecordedBufferHeight!==e&&(this._lastRecordedBufferHeight=e,this._scrollArea.style.height=this._lastRecordedBufferHeight+"px")}const e=this._bufferService.buffer.ydisp*this._currentRowHeight;this._viewportElement.scrollTop!==e&&(this._ignoreNextScrollEvent=!0,this._viewportElement.scrollTop=e),this._refreshAnimationFrame=null}syncScrollArea(e=!1){if(this._lastRecordedBufferLength!==this._bufferService.buffer.lines.length)return this._lastRecordedBufferLength=this._bufferService.buffer.lines.length,void this._refresh(e);this._lastRecordedViewportHeight===this._renderService.dimensions.css.canvas.height&&this._lastScrollTop===this._activeBuffer.ydisp*this._currentRowHeight&&this._renderDimensions.device.cell.height===this._currentDeviceCellHeight||this._refresh(e)}_handleScroll(e){if(this._lastScrollTop=this._viewportElement.scrollTop,!this._viewportElement.offsetParent)return;if(this._ignoreNextScrollEvent)return this._ignoreNextScrollEvent=!1,void this._onRequestScrollLines.fire({amount:0,suppressScrollEvent:!0});const t=Math.round(this._lastScrollTop/this._currentRowHeight)-this._bufferService.buffer.ydisp;this._onRequestScrollLines.fire({amount:t,suppressScrollEvent:!0})}_smoothScroll(){if(this._isDisposed||-1===this._smoothScrollState.origin||-1===this._smoothScrollState.target)return;const e=this._smoothScrollPercent();this._viewportElement.scrollTop=this._smoothScrollState.origin+Math.round(e*(this._smoothScrollState.target-this._smoothScrollState.origin)),e<1?this._coreBrowserService.window.requestAnimationFrame((()=>this._smoothScroll())):this._clearSmoothScrollState()}_smoothScrollPercent(){return this._optionsService.rawOptions.smoothScrollDuration&&this._smoothScrollState.startTime?Math.max(Math.min((Date.now()-this._smoothScrollState.startTime)/this._optionsService.rawOptions.smoothScrollDuration,1),0):1}_clearSmoothScrollState(){this._smoothScrollState.startTime=0,this._smoothScrollState.origin=-1,this._smoothScrollState.target=-1}_bubbleScroll(e,t){const i=this._viewportElement.scrollTop+this._lastRecordedViewportHeight;return!(t<0&&0!==this._viewportElement.scrollTop||t>0&&i0&&(i=e),s=""}}return{bufferElements:r,cursorElement:i}}getLinesScrolled(e){if(0===e.deltaY||e.shiftKey)return 0;let t=this._applyScrollModifier(e.deltaY,e);return e.deltaMode===WheelEvent.DOM_DELTA_PIXEL?(t/=this._currentRowHeight+0,this._wheelPartialScroll+=t,t=Math.floor(Math.abs(this._wheelPartialScroll))*(this._wheelPartialScroll>0?1:-1),this._wheelPartialScroll%=1):e.deltaMode===WheelEvent.DOM_DELTA_PAGE&&(t*=this._bufferService.rows),t}_applyScrollModifier(e,t){const i=this._optionsService.rawOptions.fastScrollModifier;return"alt"===i&&t.altKey||"ctrl"===i&&t.ctrlKey||"shift"===i&&t.shiftKey?e*this._optionsService.rawOptions.fastScrollSensitivity*this._optionsService.rawOptions.scrollSensitivity:e*this._optionsService.rawOptions.scrollSensitivity}handleTouchStart(e){this._lastTouchY=e.touches[0].pageY}handleTouchMove(e){const t=this._lastTouchY-e.touches[0].pageY;return this._lastTouchY=e.touches[0].pageY,0!==t&&(this._viewportElement.scrollTop+=t,this._bubbleScroll(e,t))}};t.Viewport=l=s([r(2,c.IBufferService),r(3,c.IOptionsService),r(4,o.ICharSizeService),r(5,o.IRenderService),r(6,o.ICoreBrowserService),r(7,o.IThemeService)],l)},3107:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.BufferDecorationRenderer=void 0;const n=i(4725),o=i(844),a=i(2585);let h=t.BufferDecorationRenderer=class extends o.Disposable{constructor(e,t,i,s,r){super(),this._screenElement=e,this._bufferService=t,this._coreBrowserService=i,this._decorationService=s,this._renderService=r,this._decorationElements=new Map,this._altBufferIsActive=!1,this._dimensionsChanged=!1,this._container=document.createElement("div"),this._container.classList.add("xterm-decoration-container"),this._screenElement.appendChild(this._container),this.register(this._renderService.onRenderedViewportChange((()=>this._doRefreshDecorations()))),this.register(this._renderService.onDimensionsChange((()=>{this._dimensionsChanged=!0,this._queueRefresh()}))),this.register(this._coreBrowserService.onDprChange((()=>this._queueRefresh()))),this.register(this._bufferService.buffers.onBufferActivate((()=>{this._altBufferIsActive=this._bufferService.buffer===this._bufferService.buffers.alt}))),this.register(this._decorationService.onDecorationRegistered((()=>this._queueRefresh()))),this.register(this._decorationService.onDecorationRemoved((e=>this._removeDecoration(e)))),this.register((0,o.toDisposable)((()=>{this._container.remove(),this._decorationElements.clear()})))}_queueRefresh(){void 0===this._animationFrame&&(this._animationFrame=this._renderService.addRefreshCallback((()=>{this._doRefreshDecorations(),this._animationFrame=void 0})))}_doRefreshDecorations(){for(const e of this._decorationService.decorations)this._renderDecoration(e);this._dimensionsChanged=!1}_renderDecoration(e){this._refreshStyle(e),this._dimensionsChanged&&this._refreshXPosition(e)}_createElement(e){const t=this._coreBrowserService.mainDocument.createElement("div");t.classList.add("xterm-decoration"),t.classList.toggle("xterm-decoration-top-layer","top"===e?.options?.layer),t.style.width=`${Math.round((e.options.width||1)*this._renderService.dimensions.css.cell.width)}px`,t.style.height=(e.options.height||1)*this._renderService.dimensions.css.cell.height+"px",t.style.top=(e.marker.line-this._bufferService.buffers.active.ydisp)*this._renderService.dimensions.css.cell.height+"px",t.style.lineHeight=`${this._renderService.dimensions.css.cell.height}px`;const i=e.options.x??0;return i&&i>this._bufferService.cols&&(t.style.display="none"),this._refreshXPosition(e,t),t}_refreshStyle(e){const t=e.marker.line-this._bufferService.buffers.active.ydisp;if(t<0||t>=this._bufferService.rows)e.element&&(e.element.style.display="none",e.onRenderEmitter.fire(e.element));else{let i=this._decorationElements.get(e);i||(i=this._createElement(e),e.element=i,this._decorationElements.set(e,i),this._container.appendChild(i),e.onDispose((()=>{this._decorationElements.delete(e),i.remove()}))),i.style.top=t*this._renderService.dimensions.css.cell.height+"px",i.style.display=this._altBufferIsActive?"none":"block",e.onRenderEmitter.fire(i)}}_refreshXPosition(e,t=e.element){if(!t)return;const i=e.options.x??0;"right"===(e.options.anchor||"left")?t.style.right=i?i*this._renderService.dimensions.css.cell.width+"px":"":t.style.left=i?i*this._renderService.dimensions.css.cell.width+"px":""}_removeDecoration(e){this._decorationElements.get(e)?.remove(),this._decorationElements.delete(e),e.dispose()}};t.BufferDecorationRenderer=h=s([r(1,a.IBufferService),r(2,n.ICoreBrowserService),r(3,a.IDecorationService),r(4,n.IRenderService)],h)},5871:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ColorZoneStore=void 0,t.ColorZoneStore=class{constructor(){this._zones=[],this._zonePool=[],this._zonePoolIndex=0,this._linePadding={full:0,left:0,center:0,right:0}}get zones(){return this._zonePool.length=Math.min(this._zonePool.length,this._zones.length),this._zones}clear(){this._zones.length=0,this._zonePoolIndex=0}addDecoration(e){if(e.options.overviewRulerOptions){for(const t of this._zones)if(t.color===e.options.overviewRulerOptions.color&&t.position===e.options.overviewRulerOptions.position){if(this._lineIntersectsZone(t,e.marker.line))return;if(this._lineAdjacentToZone(t,e.marker.line,e.options.overviewRulerOptions.position))return void this._addLineToZone(t,e.marker.line)}if(this._zonePoolIndex=e.startBufferLine&&t<=e.endBufferLine}_lineAdjacentToZone(e,t,i){return t>=e.startBufferLine-this._linePadding[i||"full"]&&t<=e.endBufferLine+this._linePadding[i||"full"]}_addLineToZone(e,t){e.startBufferLine=Math.min(e.startBufferLine,t),e.endBufferLine=Math.max(e.endBufferLine,t)}}},5744:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OverviewRulerRenderer=void 0;const n=i(5871),o=i(4725),a=i(844),h=i(2585),c={full:0,left:0,center:0,right:0},l={full:0,left:0,center:0,right:0},d={full:0,left:0,center:0,right:0};let _=t.OverviewRulerRenderer=class extends a.Disposable{get _width(){return this._optionsService.options.overviewRulerWidth||0}constructor(e,t,i,s,r,o,h){super(),this._viewportElement=e,this._screenElement=t,this._bufferService=i,this._decorationService=s,this._renderService=r,this._optionsService=o,this._coreBrowserService=h,this._colorZoneStore=new n.ColorZoneStore,this._shouldUpdateDimensions=!0,this._shouldUpdateAnchor=!0,this._lastKnownBufferLength=0,this._canvas=this._coreBrowserService.mainDocument.createElement("canvas"),this._canvas.classList.add("xterm-decoration-overview-ruler"),this._refreshCanvasDimensions(),this._viewportElement.parentElement?.insertBefore(this._canvas,this._viewportElement);const c=this._canvas.getContext("2d");if(!c)throw new Error("Ctx cannot be null");this._ctx=c,this._registerDecorationListeners(),this._registerBufferChangeListeners(),this._registerDimensionChangeListeners(),this.register((0,a.toDisposable)((()=>{this._canvas?.remove()})))}_registerDecorationListeners(){this.register(this._decorationService.onDecorationRegistered((()=>this._queueRefresh(void 0,!0)))),this.register(this._decorationService.onDecorationRemoved((()=>this._queueRefresh(void 0,!0))))}_registerBufferChangeListeners(){this.register(this._renderService.onRenderedViewportChange((()=>this._queueRefresh()))),this.register(this._bufferService.buffers.onBufferActivate((()=>{this._canvas.style.display=this._bufferService.buffer===this._bufferService.buffers.alt?"none":"block"}))),this.register(this._bufferService.onScroll((()=>{this._lastKnownBufferLength!==this._bufferService.buffers.normal.lines.length&&(this._refreshDrawHeightConstants(),this._refreshColorZonePadding())})))}_registerDimensionChangeListeners(){this.register(this._renderService.onRender((()=>{this._containerHeight&&this._containerHeight===this._screenElement.clientHeight||(this._queueRefresh(!0),this._containerHeight=this._screenElement.clientHeight)}))),this.register(this._optionsService.onSpecificOptionChange("overviewRulerWidth",(()=>this._queueRefresh(!0)))),this.register(this._coreBrowserService.onDprChange((()=>this._queueRefresh(!0)))),this._queueRefresh(!0)}_refreshDrawConstants(){const e=Math.floor(this._canvas.width/3),t=Math.ceil(this._canvas.width/3);l.full=this._canvas.width,l.left=e,l.center=t,l.right=e,this._refreshDrawHeightConstants(),d.full=0,d.left=0,d.center=l.left,d.right=l.left+l.center}_refreshDrawHeightConstants(){c.full=Math.round(2*this._coreBrowserService.dpr);const e=this._canvas.height/this._bufferService.buffer.lines.length,t=Math.round(Math.max(Math.min(e,12),6)*this._coreBrowserService.dpr);c.left=t,c.center=t,c.right=t}_refreshColorZonePadding(){this._colorZoneStore.setPadding({full:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*c.full),left:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*c.left),center:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*c.center),right:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*c.right)}),this._lastKnownBufferLength=this._bufferService.buffers.normal.lines.length}_refreshCanvasDimensions(){this._canvas.style.width=`${this._width}px`,this._canvas.width=Math.round(this._width*this._coreBrowserService.dpr),this._canvas.style.height=`${this._screenElement.clientHeight}px`,this._canvas.height=Math.round(this._screenElement.clientHeight*this._coreBrowserService.dpr),this._refreshDrawConstants(),this._refreshColorZonePadding()}_refreshDecorations(){this._shouldUpdateDimensions&&this._refreshCanvasDimensions(),this._ctx.clearRect(0,0,this._canvas.width,this._canvas.height),this._colorZoneStore.clear();for(const e of this._decorationService.decorations)this._colorZoneStore.addDecoration(e);this._ctx.lineWidth=1;const e=this._colorZoneStore.zones;for(const t of e)"full"!==t.position&&this._renderColorZone(t);for(const t of e)"full"===t.position&&this._renderColorZone(t);this._shouldUpdateDimensions=!1,this._shouldUpdateAnchor=!1}_renderColorZone(e){this._ctx.fillStyle=e.color,this._ctx.fillRect(d[e.position||"full"],Math.round((this._canvas.height-1)*(e.startBufferLine/this._bufferService.buffers.active.lines.length)-c[e.position||"full"]/2),l[e.position||"full"],Math.round((this._canvas.height-1)*((e.endBufferLine-e.startBufferLine)/this._bufferService.buffers.active.lines.length)+c[e.position||"full"]))}_queueRefresh(e,t){this._shouldUpdateDimensions=e||this._shouldUpdateDimensions,this._shouldUpdateAnchor=t||this._shouldUpdateAnchor,void 0===this._animationFrame&&(this._animationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>{this._refreshDecorations(),this._animationFrame=void 0})))}};t.OverviewRulerRenderer=_=s([r(2,h.IBufferService),r(3,h.IDecorationService),r(4,o.IRenderService),r(5,h.IOptionsService),r(6,o.ICoreBrowserService)],_)},2950:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CompositionHelper=void 0;const n=i(4725),o=i(2585),a=i(2584);let h=t.CompositionHelper=class{get isComposing(){return this._isComposing}constructor(e,t,i,s,r,n){this._textarea=e,this._compositionView=t,this._bufferService=i,this._optionsService=s,this._coreService=r,this._renderService=n,this._isComposing=!1,this._isSendingComposition=!1,this._compositionPosition={start:0,end:0},this._dataAlreadySent=""}compositionstart(){this._isComposing=!0,this._compositionPosition.start=this._textarea.value.length,this._compositionView.textContent="",this._dataAlreadySent="",this._compositionView.classList.add("active")}compositionupdate(e){this._compositionView.textContent=e.data,this.updateCompositionElements(),setTimeout((()=>{this._compositionPosition.end=this._textarea.value.length}),0)}compositionend(){this._finalizeComposition(!0)}keydown(e){if(this._isComposing||this._isSendingComposition){if(229===e.keyCode)return!1;if(16===e.keyCode||17===e.keyCode||18===e.keyCode)return!1;this._finalizeComposition(!1)}return 229!==e.keyCode||(this._handleAnyTextareaChanges(),!1)}_finalizeComposition(e){if(this._compositionView.classList.remove("active"),this._isComposing=!1,e){const e={start:this._compositionPosition.start,end:this._compositionPosition.end};this._isSendingComposition=!0,setTimeout((()=>{if(this._isSendingComposition){let t;this._isSendingComposition=!1,e.start+=this._dataAlreadySent.length,t=this._isComposing?this._textarea.value.substring(e.start,e.end):this._textarea.value.substring(e.start),t.length>0&&this._coreService.triggerDataEvent(t,!0)}}),0)}else{this._isSendingComposition=!1;const e=this._textarea.value.substring(this._compositionPosition.start,this._compositionPosition.end);this._coreService.triggerDataEvent(e,!0)}}_handleAnyTextareaChanges(){const e=this._textarea.value;setTimeout((()=>{if(!this._isComposing){const t=this._textarea.value,i=t.replace(e,"");this._dataAlreadySent=i,t.length>e.length?this._coreService.triggerDataEvent(i,!0):t.lengththis.updateCompositionElements(!0)),0)}}};t.CompositionHelper=h=s([r(2,o.IBufferService),r(3,o.IOptionsService),r(4,o.ICoreService),r(5,n.IRenderService)],h)},9806:(e,t)=>{function i(e,t,i){const s=i.getBoundingClientRect(),r=e.getComputedStyle(i),n=parseInt(r.getPropertyValue("padding-left")),o=parseInt(r.getPropertyValue("padding-top"));return[t.clientX-s.left-n,t.clientY-s.top-o]}Object.defineProperty(t,"__esModule",{value:!0}),t.getCoords=t.getCoordsRelativeToElement=void 0,t.getCoordsRelativeToElement=i,t.getCoords=function(e,t,s,r,n,o,a,h,c){if(!o)return;const l=i(e,t,s);return l?(l[0]=Math.ceil((l[0]+(c?a/2:0))/a),l[1]=Math.ceil(l[1]/h),l[0]=Math.min(Math.max(l[0],1),r+(c?1:0)),l[1]=Math.min(Math.max(l[1],1),n),l):void 0}},9504:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.moveToCellSequence=void 0;const s=i(2584);function r(e,t,i,s){const r=e-n(e,i),a=t-n(t,i),l=Math.abs(r-a)-function(e,t,i){let s=0;const r=e-n(e,i),a=t-n(t,i);for(let n=0;n=0&&et?"A":"B"}function a(e,t,i,s,r,n){let o=e,a=t,h="";for(;o!==i||a!==s;)o+=r?1:-1,r&&o>n.cols-1?(h+=n.buffer.translateBufferLineToString(a,!1,e,o),o=0,e=0,a++):!r&&o<0&&(h+=n.buffer.translateBufferLineToString(a,!1,0,e+1),o=n.cols-1,e=o,a--);return h+n.buffer.translateBufferLineToString(a,!1,e,o)}function h(e,t){const i=t?"O":"[";return s.C0.ESC+i+e}function c(e,t){e=Math.floor(e);let i="";for(let s=0;s0?s-n(s,o):t;const _=s,u=function(e,t,i,s,o,a){let h;return h=r(i,s,o,a).length>0?s-n(s,o):t,e=i&&he?"D":"C",c(Math.abs(o-e),h(d,s));d=l>t?"D":"C";const _=Math.abs(l-t);return c(function(e,t){return t.cols-e}(l>t?e:o,i)+(_-1)*i.cols+1+((l>t?o:e)-1),h(d,s))}},1296:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.DomRenderer=void 0;const n=i(3787),o=i(2550),a=i(2223),h=i(6171),c=i(6052),l=i(4725),d=i(8055),_=i(8460),u=i(844),f=i(2585),v="xterm-dom-renderer-owner-",p="xterm-rows",g="xterm-fg-",m="xterm-bg-",S="xterm-focus",C="xterm-selection";let b=1,w=t.DomRenderer=class extends u.Disposable{constructor(e,t,i,s,r,a,l,d,f,g,m,S,w){super(),this._terminal=e,this._document=t,this._element=i,this._screenElement=s,this._viewportElement=r,this._helperContainer=a,this._linkifier2=l,this._charSizeService=f,this._optionsService=g,this._bufferService=m,this._coreBrowserService=S,this._themeService=w,this._terminalClass=b++,this._rowElements=[],this._selectionRenderModel=(0,c.createSelectionRenderModel)(),this.onRequestRedraw=this.register(new _.EventEmitter).event,this._rowContainer=this._document.createElement("div"),this._rowContainer.classList.add(p),this._rowContainer.style.lineHeight="normal",this._rowContainer.setAttribute("aria-hidden","true"),this._refreshRowElements(this._bufferService.cols,this._bufferService.rows),this._selectionContainer=this._document.createElement("div"),this._selectionContainer.classList.add(C),this._selectionContainer.setAttribute("aria-hidden","true"),this.dimensions=(0,h.createRenderDimensions)(),this._updateDimensions(),this.register(this._optionsService.onOptionChange((()=>this._handleOptionsChanged()))),this.register(this._themeService.onChangeColors((e=>this._injectCss(e)))),this._injectCss(this._themeService.colors),this._rowFactory=d.createInstance(n.DomRendererRowFactory,document),this._element.classList.add(v+this._terminalClass),this._screenElement.appendChild(this._rowContainer),this._screenElement.appendChild(this._selectionContainer),this.register(this._linkifier2.onShowLinkUnderline((e=>this._handleLinkHover(e)))),this.register(this._linkifier2.onHideLinkUnderline((e=>this._handleLinkLeave(e)))),this.register((0,u.toDisposable)((()=>{this._element.classList.remove(v+this._terminalClass),this._rowContainer.remove(),this._selectionContainer.remove(),this._widthCache.dispose(),this._themeStyleElement.remove(),this._dimensionsStyleElement.remove()}))),this._widthCache=new o.WidthCache(this._document,this._helperContainer),this._widthCache.setFont(this._optionsService.rawOptions.fontFamily,this._optionsService.rawOptions.fontSize,this._optionsService.rawOptions.fontWeight,this._optionsService.rawOptions.fontWeightBold),this._setDefaultSpacing()}_updateDimensions(){const e=this._coreBrowserService.dpr;this.dimensions.device.char.width=this._charSizeService.width*e,this.dimensions.device.char.height=Math.ceil(this._charSizeService.height*e),this.dimensions.device.cell.width=this.dimensions.device.char.width+Math.round(this._optionsService.rawOptions.letterSpacing),this.dimensions.device.cell.height=Math.floor(this.dimensions.device.char.height*this._optionsService.rawOptions.lineHeight),this.dimensions.device.char.left=0,this.dimensions.device.char.top=0,this.dimensions.device.canvas.width=this.dimensions.device.cell.width*this._bufferService.cols,this.dimensions.device.canvas.height=this.dimensions.device.cell.height*this._bufferService.rows,this.dimensions.css.canvas.width=Math.round(this.dimensions.device.canvas.width/e),this.dimensions.css.canvas.height=Math.round(this.dimensions.device.canvas.height/e),this.dimensions.css.cell.width=this.dimensions.css.canvas.width/this._bufferService.cols,this.dimensions.css.cell.height=this.dimensions.css.canvas.height/this._bufferService.rows;for(const e of this._rowElements)e.style.width=`${this.dimensions.css.canvas.width}px`,e.style.height=`${this.dimensions.css.cell.height}px`,e.style.lineHeight=`${this.dimensions.css.cell.height}px`,e.style.overflow="hidden";this._dimensionsStyleElement||(this._dimensionsStyleElement=this._document.createElement("style"),this._screenElement.appendChild(this._dimensionsStyleElement));const t=`${this._terminalSelector} .${p} span { display: inline-block; height: 100%; vertical-align: top;}`;this._dimensionsStyleElement.textContent=t,this._selectionContainer.style.height=this._viewportElement.style.height,this._screenElement.style.width=`${this.dimensions.css.canvas.width}px`,this._screenElement.style.height=`${this.dimensions.css.canvas.height}px`}_injectCss(e){this._themeStyleElement||(this._themeStyleElement=this._document.createElement("style"),this._screenElement.appendChild(this._themeStyleElement));let t=`${this._terminalSelector} .${p} { color: ${e.foreground.css}; font-family: ${this._optionsService.rawOptions.fontFamily}; font-size: ${this._optionsService.rawOptions.fontSize}px; font-kerning: none; white-space: pre}`;t+=`${this._terminalSelector} .${p} .xterm-dim { color: ${d.color.multiplyOpacity(e.foreground,.5).css};}`,t+=`${this._terminalSelector} span:not(.xterm-bold) { font-weight: ${this._optionsService.rawOptions.fontWeight};}${this._terminalSelector} span.xterm-bold { font-weight: ${this._optionsService.rawOptions.fontWeightBold};}${this._terminalSelector} span.xterm-italic { font-style: italic;}`;const i=`blink_underline_${this._terminalClass}`,s=`blink_bar_${this._terminalClass}`,r=`blink_block_${this._terminalClass}`;t+=`@keyframes ${i} { 50% { border-bottom-style: hidden; }}`,t+=`@keyframes ${s} { 50% { box-shadow: none; }}`,t+=`@keyframes ${r} { 0% { background-color: ${e.cursor.css}; color: ${e.cursorAccent.css}; } 50% { background-color: inherit; color: ${e.cursor.css}; }}`,t+=`${this._terminalSelector} .${p}.${S} .xterm-cursor.xterm-cursor-blink.xterm-cursor-underline { animation: ${i} 1s step-end infinite;}${this._terminalSelector} .${p}.${S} .xterm-cursor.xterm-cursor-blink.xterm-cursor-bar { animation: ${s} 1s step-end infinite;}${this._terminalSelector} .${p}.${S} .xterm-cursor.xterm-cursor-blink.xterm-cursor-block { animation: ${r} 1s step-end infinite;}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-block { background-color: ${e.cursor.css}; color: ${e.cursorAccent.css};}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-block:not(.xterm-cursor-blink) { background-color: ${e.cursor.css} !important; color: ${e.cursorAccent.css} !important;}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-outline { outline: 1px solid ${e.cursor.css}; outline-offset: -1px;}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-bar { box-shadow: ${this._optionsService.rawOptions.cursorWidth}px 0 0 ${e.cursor.css} inset;}${this._terminalSelector} .${p} .xterm-cursor.xterm-cursor-underline { border-bottom: 1px ${e.cursor.css}; border-bottom-style: solid; height: calc(100% - 1px);}`,t+=`${this._terminalSelector} .${C} { position: absolute; top: 0; left: 0; z-index: 1; pointer-events: none;}${this._terminalSelector}.focus .${C} div { position: absolute; background-color: ${e.selectionBackgroundOpaque.css};}${this._terminalSelector} .${C} div { position: absolute; background-color: ${e.selectionInactiveBackgroundOpaque.css};}`;for(const[i,s]of e.ansi.entries())t+=`${this._terminalSelector} .${g}${i} { color: ${s.css}; }${this._terminalSelector} .${g}${i}.xterm-dim { color: ${d.color.multiplyOpacity(s,.5).css}; }${this._terminalSelector} .${m}${i} { background-color: ${s.css}; }`;t+=`${this._terminalSelector} .${g}${a.INVERTED_DEFAULT_COLOR} { color: ${d.color.opaque(e.background).css}; }${this._terminalSelector} .${g}${a.INVERTED_DEFAULT_COLOR}.xterm-dim { color: ${d.color.multiplyOpacity(d.color.opaque(e.background),.5).css}; }${this._terminalSelector} .${m}${a.INVERTED_DEFAULT_COLOR} { background-color: ${e.foreground.css}; }`,this._themeStyleElement.textContent=t}_setDefaultSpacing(){const e=this.dimensions.css.cell.width-this._widthCache.get("W",!1,!1);this._rowContainer.style.letterSpacing=`${e}px`,this._rowFactory.defaultSpacing=e}handleDevicePixelRatioChange(){this._updateDimensions(),this._widthCache.clear(),this._setDefaultSpacing()}_refreshRowElements(e,t){for(let e=this._rowElements.length;e<=t;e++){const e=this._document.createElement("div");this._rowContainer.appendChild(e),this._rowElements.push(e)}for(;this._rowElements.length>t;)this._rowContainer.removeChild(this._rowElements.pop())}handleResize(e,t){this._refreshRowElements(e,t),this._updateDimensions(),this.handleSelectionChanged(this._selectionRenderModel.selectionStart,this._selectionRenderModel.selectionEnd,this._selectionRenderModel.columnSelectMode)}handleCharSizeChanged(){this._updateDimensions(),this._widthCache.clear(),this._setDefaultSpacing()}handleBlur(){this._rowContainer.classList.remove(S),this.renderRows(0,this._bufferService.rows-1)}handleFocus(){this._rowContainer.classList.add(S),this.renderRows(this._bufferService.buffer.y,this._bufferService.buffer.y)}handleSelectionChanged(e,t,i){if(this._selectionContainer.replaceChildren(),this._rowFactory.handleSelectionChanged(e,t,i),this.renderRows(0,this._bufferService.rows-1),!e||!t)return;this._selectionRenderModel.update(this._terminal,e,t,i);const s=this._selectionRenderModel.viewportStartRow,r=this._selectionRenderModel.viewportEndRow,n=this._selectionRenderModel.viewportCappedStartRow,o=this._selectionRenderModel.viewportCappedEndRow;if(n>=this._bufferService.rows||o<0)return;const a=this._document.createDocumentFragment();if(i){const i=e[0]>t[0];a.appendChild(this._createSelectionElement(n,i?t[0]:e[0],i?e[0]:t[0],o-n+1))}else{const i=s===n?e[0]:0,h=n===r?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(n,i,h));const c=o-n-1;if(a.appendChild(this._createSelectionElement(n+1,0,this._bufferService.cols,c)),n!==o){const e=r===o?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(o,0,e))}}this._selectionContainer.appendChild(a)}_createSelectionElement(e,t,i,s=1){const r=this._document.createElement("div"),n=t*this.dimensions.css.cell.width;let o=this.dimensions.css.cell.width*(i-t);return n+o>this.dimensions.css.canvas.width&&(o=this.dimensions.css.canvas.width-n),r.style.height=s*this.dimensions.css.cell.height+"px",r.style.top=e*this.dimensions.css.cell.height+"px",r.style.left=`${n}px`,r.style.width=`${o}px`,r}handleCursorMove(){}_handleOptionsChanged(){this._updateDimensions(),this._injectCss(this._themeService.colors),this._widthCache.setFont(this._optionsService.rawOptions.fontFamily,this._optionsService.rawOptions.fontSize,this._optionsService.rawOptions.fontWeight,this._optionsService.rawOptions.fontWeightBold),this._setDefaultSpacing()}clear(){for(const e of this._rowElements)e.replaceChildren()}renderRows(e,t){const i=this._bufferService.buffer,s=i.ybase+i.y,r=Math.min(i.x,this._bufferService.cols-1),n=this._optionsService.rawOptions.cursorBlink,o=this._optionsService.rawOptions.cursorStyle,a=this._optionsService.rawOptions.cursorInactiveStyle;for(let h=e;h<=t;h++){const e=h+i.ydisp,t=this._rowElements[h],c=i.lines.get(e);if(!t||!c)break;t.replaceChildren(...this._rowFactory.createRow(c,e,e===s,o,a,r,n,this.dimensions.css.cell.width,this._widthCache,-1,-1))}}get _terminalSelector(){return`.${v}${this._terminalClass}`}_handleLinkHover(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!0)}_handleLinkLeave(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!1)}_setCellUnderline(e,t,i,s,r,n){i<0&&(e=0),s<0&&(t=0);const o=this._bufferService.rows-1;i=Math.max(Math.min(i,o),0),s=Math.max(Math.min(s,o),0),r=Math.min(r,this._bufferService.cols);const a=this._bufferService.buffer,h=a.ybase+a.y,c=Math.min(a.x,r-1),l=this._optionsService.rawOptions.cursorBlink,d=this._optionsService.rawOptions.cursorStyle,_=this._optionsService.rawOptions.cursorInactiveStyle;for(let o=i;o<=s;++o){const u=o+a.ydisp,f=this._rowElements[o],v=a.lines.get(u);if(!f||!v)break;f.replaceChildren(...this._rowFactory.createRow(v,u,u===h,d,_,c,l,this.dimensions.css.cell.width,this._widthCache,n?o===i?e:0:-1,n?(o===s?t:r)-1:-1))}}};t.DomRenderer=w=s([r(7,f.IInstantiationService),r(8,l.ICharSizeService),r(9,f.IOptionsService),r(10,f.IBufferService),r(11,l.ICoreBrowserService),r(12,l.IThemeService)],w)},3787:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.DomRendererRowFactory=void 0;const n=i(2223),o=i(643),a=i(511),h=i(2585),c=i(8055),l=i(4725),d=i(4269),_=i(6171),u=i(3734);let f=t.DomRendererRowFactory=class{constructor(e,t,i,s,r,n,o){this._document=e,this._characterJoinerService=t,this._optionsService=i,this._coreBrowserService=s,this._coreService=r,this._decorationService=n,this._themeService=o,this._workCell=new a.CellData,this._columnSelectMode=!1,this.defaultSpacing=0}handleSelectionChanged(e,t,i){this._selectionStart=e,this._selectionEnd=t,this._columnSelectMode=i}createRow(e,t,i,s,r,a,h,l,_,f,p){const g=[],m=this._characterJoinerService.getJoinedCharacters(t),S=this._themeService.colors;let C,b=e.getNoBgTrimmedLength();i&&b0&&M===m[0][0]){O=!0;const t=m.shift();I=new d.JoinedCellData(this._workCell,e.translateToString(!0,t[0],t[1]),t[1]-t[0]),P=t[1]-1,b=I.getWidth()}const H=this._isCellInSelection(M,t),F=i&&M===a,W=T&&M>=f&&M<=p;let U=!1;this._decorationService.forEachDecorationAtCell(M,t,void 0,(e=>{U=!0}));let N=I.getChars()||o.WHITESPACE_CELL_CHAR;if(" "===N&&(I.isUnderline()||I.isOverline())&&(N=" "),A=b*l-_.get(N,I.isBold(),I.isItalic()),C){if(w&&(H&&x||!H&&!x&&I.bg===E)&&(H&&x&&S.selectionForeground||I.fg===k)&&I.extended.ext===L&&W===D&&A===R&&!F&&!O&&!U){I.isInvisible()?y+=o.WHITESPACE_CELL_CHAR:y+=N,w++;continue}w&&(C.textContent=y),C=this._document.createElement("span"),w=0,y=""}else C=this._document.createElement("span");if(E=I.bg,k=I.fg,L=I.extended.ext,D=W,R=A,x=H,O&&a>=M&&a<=P&&(a=M),!this._coreService.isCursorHidden&&F&&this._coreService.isCursorInitialized)if(B.push("xterm-cursor"),this._coreBrowserService.isFocused)h&&B.push("xterm-cursor-blink"),B.push("bar"===s?"xterm-cursor-bar":"underline"===s?"xterm-cursor-underline":"xterm-cursor-block");else if(r)switch(r){case"outline":B.push("xterm-cursor-outline");break;case"block":B.push("xterm-cursor-block");break;case"bar":B.push("xterm-cursor-bar");break;case"underline":B.push("xterm-cursor-underline")}if(I.isBold()&&B.push("xterm-bold"),I.isItalic()&&B.push("xterm-italic"),I.isDim()&&B.push("xterm-dim"),y=I.isInvisible()?o.WHITESPACE_CELL_CHAR:I.getChars()||o.WHITESPACE_CELL_CHAR,I.isUnderline()&&(B.push(`xterm-underline-${I.extended.underlineStyle}`)," "===y&&(y=" "),!I.isUnderlineColorDefault()))if(I.isUnderlineColorRGB())C.style.textDecorationColor=`rgb(${u.AttributeData.toColorRGB(I.getUnderlineColor()).join(",")})`;else{let e=I.getUnderlineColor();this._optionsService.rawOptions.drawBoldTextInBrightColors&&I.isBold()&&e<8&&(e+=8),C.style.textDecorationColor=S.ansi[e].css}I.isOverline()&&(B.push("xterm-overline")," "===y&&(y=" ")),I.isStrikethrough()&&B.push("xterm-strikethrough"),W&&(C.style.textDecoration="underline");let $=I.getFgColor(),j=I.getFgColorMode(),z=I.getBgColor(),K=I.getBgColorMode();const q=!!I.isInverse();if(q){const e=$;$=z,z=e;const t=j;j=K,K=t}let V,G,X,J=!1;switch(this._decorationService.forEachDecorationAtCell(M,t,void 0,(e=>{"top"!==e.options.layer&&J||(e.backgroundColorRGB&&(K=50331648,z=e.backgroundColorRGB.rgba>>8&16777215,V=e.backgroundColorRGB),e.foregroundColorRGB&&(j=50331648,$=e.foregroundColorRGB.rgba>>8&16777215,G=e.foregroundColorRGB),J="top"===e.options.layer)})),!J&&H&&(V=this._coreBrowserService.isFocused?S.selectionBackgroundOpaque:S.selectionInactiveBackgroundOpaque,z=V.rgba>>8&16777215,K=50331648,J=!0,S.selectionForeground&&(j=50331648,$=S.selectionForeground.rgba>>8&16777215,G=S.selectionForeground)),J&&B.push("xterm-decoration-top"),K){case 16777216:case 33554432:X=S.ansi[z],B.push(`xterm-bg-${z}`);break;case 50331648:X=c.channels.toColor(z>>16,z>>8&255,255&z),this._addStyle(C,`background-color:#${v((z>>>0).toString(16),"0",6)}`);break;default:q?(X=S.foreground,B.push(`xterm-bg-${n.INVERTED_DEFAULT_COLOR}`)):X=S.background}switch(V||I.isDim()&&(V=c.color.multiplyOpacity(X,.5)),j){case 16777216:case 33554432:I.isBold()&&$<8&&this._optionsService.rawOptions.drawBoldTextInBrightColors&&($+=8),this._applyMinimumContrast(C,X,S.ansi[$],I,V,void 0)||B.push(`xterm-fg-${$}`);break;case 50331648:const e=c.channels.toColor($>>16&255,$>>8&255,255&$);this._applyMinimumContrast(C,X,e,I,V,G)||this._addStyle(C,`color:#${v($.toString(16),"0",6)}`);break;default:this._applyMinimumContrast(C,X,S.foreground,I,V,G)||q&&B.push(`xterm-fg-${n.INVERTED_DEFAULT_COLOR}`)}B.length&&(C.className=B.join(" "),B.length=0),F||O||U?C.textContent=y:w++,A!==this.defaultSpacing&&(C.style.letterSpacing=`${A}px`),g.push(C),M=P}return C&&w&&(C.textContent=y),g}_applyMinimumContrast(e,t,i,s,r,n){if(1===this._optionsService.rawOptions.minimumContrastRatio||(0,_.treatGlyphAsBackgroundColor)(s.getCode()))return!1;const o=this._getContrastCache(s);let a;if(r||n||(a=o.getColor(t.rgba,i.rgba)),void 0===a){const e=this._optionsService.rawOptions.minimumContrastRatio/(s.isDim()?2:1);a=c.color.ensureContrastRatio(r||t,n||i,e),o.setColor((r||t).rgba,(n||i).rgba,a??null)}return!!a&&(this._addStyle(e,`color:${a.css}`),!0)}_getContrastCache(e){return e.isDim()?this._themeService.colors.halfContrastCache:this._themeService.colors.contrastCache}_addStyle(e,t){e.setAttribute("style",`${e.getAttribute("style")||""}${t};`)}_isCellInSelection(e,t){const i=this._selectionStart,s=this._selectionEnd;return!(!i||!s)&&(this._columnSelectMode?i[0]<=s[0]?e>=i[0]&&t>=i[1]&&e=i[1]&&e>=s[0]&&t<=s[1]:t>i[1]&&t=i[0]&&e=i[0])}};function v(e,t,i){for(;e.length{Object.defineProperty(t,"__esModule",{value:!0}),t.WidthCache=void 0,t.WidthCache=class{constructor(e,t){this._flat=new Float32Array(256),this._font="",this._fontSize=0,this._weight="normal",this._weightBold="bold",this._measureElements=[],this._container=e.createElement("div"),this._container.classList.add("xterm-width-cache-measure-container"),this._container.setAttribute("aria-hidden","true"),this._container.style.whiteSpace="pre",this._container.style.fontKerning="none";const i=e.createElement("span");i.classList.add("xterm-char-measure-element");const s=e.createElement("span");s.classList.add("xterm-char-measure-element"),s.style.fontWeight="bold";const r=e.createElement("span");r.classList.add("xterm-char-measure-element"),r.style.fontStyle="italic";const n=e.createElement("span");n.classList.add("xterm-char-measure-element"),n.style.fontWeight="bold",n.style.fontStyle="italic",this._measureElements=[i,s,r,n],this._container.appendChild(i),this._container.appendChild(s),this._container.appendChild(r),this._container.appendChild(n),t.appendChild(this._container),this.clear()}dispose(){this._container.remove(),this._measureElements.length=0,this._holey=void 0}clear(){this._flat.fill(-9999),this._holey=new Map}setFont(e,t,i,s){e===this._font&&t===this._fontSize&&i===this._weight&&s===this._weightBold||(this._font=e,this._fontSize=t,this._weight=i,this._weightBold=s,this._container.style.fontFamily=this._font,this._container.style.fontSize=`${this._fontSize}px`,this._measureElements[0].style.fontWeight=`${i}`,this._measureElements[1].style.fontWeight=`${s}`,this._measureElements[2].style.fontWeight=`${i}`,this._measureElements[3].style.fontWeight=`${s}`,this.clear())}get(e,t,i){let s=0;if(!t&&!i&&1===e.length&&(s=e.charCodeAt(0))<256){if(-9999!==this._flat[s])return this._flat[s];const t=this._measure(e,0);return t>0&&(this._flat[s]=t),t}let r=e;t&&(r+="B"),i&&(r+="I");let n=this._holey.get(r);if(void 0===n){let s=0;t&&(s|=1),i&&(s|=2),n=this._measure(e,s),n>0&&this._holey.set(r,n)}return n}_measure(e,t){const i=this._measureElements[t];return i.textContent=e.repeat(32),i.offsetWidth/32}}},2223:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.TEXT_BASELINE=t.DIM_OPACITY=t.INVERTED_DEFAULT_COLOR=void 0;const s=i(6114);t.INVERTED_DEFAULT_COLOR=257,t.DIM_OPACITY=.5,t.TEXT_BASELINE=s.isFirefox||s.isLegacyEdge?"bottom":"ideographic"},6171:(e,t)=>{function i(e){return 57508<=e&&e<=57558}function s(e){return e>=128512&&e<=128591||e>=127744&&e<=128511||e>=128640&&e<=128767||e>=9728&&e<=9983||e>=9984&&e<=10175||e>=65024&&e<=65039||e>=129280&&e<=129535||e>=127462&&e<=127487}Object.defineProperty(t,"__esModule",{value:!0}),t.computeNextVariantOffset=t.createRenderDimensions=t.treatGlyphAsBackgroundColor=t.allowRescaling=t.isEmoji=t.isRestrictedPowerlineGlyph=t.isPowerlineGlyph=t.throwIfFalsy=void 0,t.throwIfFalsy=function(e){if(!e)throw new Error("value must not be falsy");return e},t.isPowerlineGlyph=i,t.isRestrictedPowerlineGlyph=function(e){return 57520<=e&&e<=57527},t.isEmoji=s,t.allowRescaling=function(e,t,r,n){return 1===t&&r>Math.ceil(1.5*n)&&void 0!==e&&e>255&&!s(e)&&!i(e)&&!function(e){return 57344<=e&&e<=63743}(e)},t.treatGlyphAsBackgroundColor=function(e){return i(e)||function(e){return 9472<=e&&e<=9631}(e)},t.createRenderDimensions=function(){return{css:{canvas:{width:0,height:0},cell:{width:0,height:0}},device:{canvas:{width:0,height:0},cell:{width:0,height:0},char:{width:0,height:0,left:0,top:0}}}},t.computeNextVariantOffset=function(e,t,i=0){return(e-(2*Math.round(t)-i))%(2*Math.round(t))}},6052:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createSelectionRenderModel=void 0;class i{constructor(){this.clear()}clear(){this.hasSelection=!1,this.columnSelectMode=!1,this.viewportStartRow=0,this.viewportEndRow=0,this.viewportCappedStartRow=0,this.viewportCappedEndRow=0,this.startCol=0,this.endCol=0,this.selectionStart=void 0,this.selectionEnd=void 0}update(e,t,i,s=!1){if(this.selectionStart=t,this.selectionEnd=i,!t||!i||t[0]===i[0]&&t[1]===i[1])return void this.clear();const r=e.buffers.active.ydisp,n=t[1]-r,o=i[1]-r,a=Math.max(n,0),h=Math.min(o,e.rows-1);a>=e.rows||h<0?this.clear():(this.hasSelection=!0,this.columnSelectMode=s,this.viewportStartRow=n,this.viewportEndRow=o,this.viewportCappedStartRow=a,this.viewportCappedEndRow=h,this.startCol=t[0],this.endCol=i[0])}isCellSelected(e,t,i){return!!this.hasSelection&&(i-=e.buffer.active.viewportY,this.columnSelectMode?this.startCol<=this.endCol?t>=this.startCol&&i>=this.viewportCappedStartRow&&t=this.viewportCappedStartRow&&t>=this.endCol&&i<=this.viewportCappedEndRow:i>this.viewportStartRow&&i=this.startCol&&t=this.startCol)}}t.createSelectionRenderModel=function(){return new i}},456:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SelectionModel=void 0,t.SelectionModel=class{constructor(e){this._bufferService=e,this.isSelectAllActive=!1,this.selectionStartLength=0}clearSelection(){this.selectionStart=void 0,this.selectionEnd=void 0,this.isSelectAllActive=!1,this.selectionStartLength=0}get finalSelectionStart(){return this.isSelectAllActive?[0,0]:this.selectionEnd&&this.selectionStart&&this.areSelectionValuesReversed()?this.selectionEnd:this.selectionStart}get finalSelectionEnd(){if(this.isSelectAllActive)return[this._bufferService.cols,this._bufferService.buffer.ybase+this._bufferService.rows-1];if(this.selectionStart){if(!this.selectionEnd||this.areSelectionValuesReversed()){const e=this.selectionStart[0]+this.selectionStartLength;return e>this._bufferService.cols?e%this._bufferService.cols==0?[this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)-1]:[e%this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)]:[e,this.selectionStart[1]]}if(this.selectionStartLength&&this.selectionEnd[1]===this.selectionStart[1]){const e=this.selectionStart[0]+this.selectionStartLength;return e>this._bufferService.cols?[e%this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)]:[Math.max(e,this.selectionEnd[0]),this.selectionEnd[1]]}return this.selectionEnd}}areSelectionValuesReversed(){const e=this.selectionStart,t=this.selectionEnd;return!(!e||!t)&&(e[1]>t[1]||e[1]===t[1]&&e[0]>t[0])}handleTrim(e){return this.selectionStart&&(this.selectionStart[1]-=e),this.selectionEnd&&(this.selectionEnd[1]-=e),this.selectionEnd&&this.selectionEnd[1]<0?(this.clearSelection(),!0):(this.selectionStart&&this.selectionStart[1]<0&&(this.selectionStart[1]=0),!1)}}},428:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CharSizeService=void 0;const n=i(2585),o=i(8460),a=i(844);let h=t.CharSizeService=class extends a.Disposable{get hasValidSize(){return this.width>0&&this.height>0}constructor(e,t,i){super(),this._optionsService=i,this.width=0,this.height=0,this._onCharSizeChange=this.register(new o.EventEmitter),this.onCharSizeChange=this._onCharSizeChange.event;try{this._measureStrategy=this.register(new d(this._optionsService))}catch{this._measureStrategy=this.register(new l(e,t,this._optionsService))}this.register(this._optionsService.onMultipleOptionChange(["fontFamily","fontSize"],(()=>this.measure())))}measure(){const e=this._measureStrategy.measure();e.width===this.width&&e.height===this.height||(this.width=e.width,this.height=e.height,this._onCharSizeChange.fire())}};t.CharSizeService=h=s([r(2,n.IOptionsService)],h);class c extends a.Disposable{constructor(){super(...arguments),this._result={width:0,height:0}}_validateAndSet(e,t){void 0!==e&&e>0&&void 0!==t&&t>0&&(this._result.width=e,this._result.height=t)}}class l extends c{constructor(e,t,i){super(),this._document=e,this._parentElement=t,this._optionsService=i,this._measureElement=this._document.createElement("span"),this._measureElement.classList.add("xterm-char-measure-element"),this._measureElement.textContent="W".repeat(32),this._measureElement.setAttribute("aria-hidden","true"),this._measureElement.style.whiteSpace="pre",this._measureElement.style.fontKerning="none",this._parentElement.appendChild(this._measureElement)}measure(){return this._measureElement.style.fontFamily=this._optionsService.rawOptions.fontFamily,this._measureElement.style.fontSize=`${this._optionsService.rawOptions.fontSize}px`,this._validateAndSet(Number(this._measureElement.offsetWidth)/32,Number(this._measureElement.offsetHeight)),this._result}}class d extends c{constructor(e){super(),this._optionsService=e,this._canvas=new OffscreenCanvas(100,100),this._ctx=this._canvas.getContext("2d");const t=this._ctx.measureText("W");if(!("width"in t&&"fontBoundingBoxAscent"in t&&"fontBoundingBoxDescent"in t))throw new Error("Required font metrics not supported")}measure(){this._ctx.font=`${this._optionsService.rawOptions.fontSize}px ${this._optionsService.rawOptions.fontFamily}`;const e=this._ctx.measureText("W");return this._validateAndSet(e.width,e.fontBoundingBoxAscent+e.fontBoundingBoxDescent),this._result}}},4269:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CharacterJoinerService=t.JoinedCellData=void 0;const n=i(3734),o=i(643),a=i(511),h=i(2585);class c extends n.AttributeData{constructor(e,t,i){super(),this.content=0,this.combinedData="",this.fg=e.fg,this.bg=e.bg,this.combinedData=t,this._width=i}isCombined(){return 2097152}getWidth(){return this._width}getChars(){return this.combinedData}getCode(){return 2097151}setFromCharData(e){throw new Error("not implemented")}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}}t.JoinedCellData=c;let l=t.CharacterJoinerService=class e{constructor(e){this._bufferService=e,this._characterJoiners=[],this._nextCharacterJoinerId=0,this._workCell=new a.CellData}register(e){const t={id:this._nextCharacterJoinerId++,handler:e};return this._characterJoiners.push(t),t.id}deregister(e){for(let t=0;t1){const e=this._getJoinedRanges(s,a,n,t,r);for(let t=0;t1){const e=this._getJoinedRanges(s,a,n,t,r);for(let t=0;t{Object.defineProperty(t,"__esModule",{value:!0}),t.CoreBrowserService=void 0;const s=i(844),r=i(8460),n=i(3656);class o extends s.Disposable{constructor(e,t,i){super(),this._textarea=e,this._window=t,this.mainDocument=i,this._isFocused=!1,this._cachedIsFocused=void 0,this._screenDprMonitor=new a(this._window),this._onDprChange=this.register(new r.EventEmitter),this.onDprChange=this._onDprChange.event,this._onWindowChange=this.register(new r.EventEmitter),this.onWindowChange=this._onWindowChange.event,this.register(this.onWindowChange((e=>this._screenDprMonitor.setWindow(e)))),this.register((0,r.forwardEvent)(this._screenDprMonitor.onDprChange,this._onDprChange)),this._textarea.addEventListener("focus",(()=>this._isFocused=!0)),this._textarea.addEventListener("blur",(()=>this._isFocused=!1))}get window(){return this._window}set window(e){this._window!==e&&(this._window=e,this._onWindowChange.fire(this._window))}get dpr(){return this.window.devicePixelRatio}get isFocused(){return void 0===this._cachedIsFocused&&(this._cachedIsFocused=this._isFocused&&this._textarea.ownerDocument.hasFocus(),queueMicrotask((()=>this._cachedIsFocused=void 0))),this._cachedIsFocused}}t.CoreBrowserService=o;class a extends s.Disposable{constructor(e){super(),this._parentWindow=e,this._windowResizeListener=this.register(new s.MutableDisposable),this._onDprChange=this.register(new r.EventEmitter),this.onDprChange=this._onDprChange.event,this._outerListener=()=>this._setDprAndFireIfDiffers(),this._currentDevicePixelRatio=this._parentWindow.devicePixelRatio,this._updateDpr(),this._setWindowResizeListener(),this.register((0,s.toDisposable)((()=>this.clearListener())))}setWindow(e){this._parentWindow=e,this._setWindowResizeListener(),this._setDprAndFireIfDiffers()}_setWindowResizeListener(){this._windowResizeListener.value=(0,n.addDisposableDomListener)(this._parentWindow,"resize",(()=>this._setDprAndFireIfDiffers()))}_setDprAndFireIfDiffers(){this._parentWindow.devicePixelRatio!==this._currentDevicePixelRatio&&this._onDprChange.fire(this._parentWindow.devicePixelRatio),this._updateDpr()}_updateDpr(){this._outerListener&&(this._resolutionMediaMatchList?.removeListener(this._outerListener),this._currentDevicePixelRatio=this._parentWindow.devicePixelRatio,this._resolutionMediaMatchList=this._parentWindow.matchMedia(`screen and (resolution: ${this._parentWindow.devicePixelRatio}dppx)`),this._resolutionMediaMatchList.addListener(this._outerListener))}clearListener(){this._resolutionMediaMatchList&&this._outerListener&&(this._resolutionMediaMatchList.removeListener(this._outerListener),this._resolutionMediaMatchList=void 0,this._outerListener=void 0)}}},779:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.LinkProviderService=void 0;const s=i(844);class r extends s.Disposable{constructor(){super(),this.linkProviders=[],this.register((0,s.toDisposable)((()=>this.linkProviders.length=0)))}registerLinkProvider(e){return this.linkProviders.push(e),{dispose:()=>{const t=this.linkProviders.indexOf(e);-1!==t&&this.linkProviders.splice(t,1)}}}}t.LinkProviderService=r},8934:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.MouseService=void 0;const n=i(4725),o=i(9806);let a=t.MouseService=class{constructor(e,t){this._renderService=e,this._charSizeService=t}getCoords(e,t,i,s,r){return(0,o.getCoords)(window,e,t,i,s,this._charSizeService.hasValidSize,this._renderService.dimensions.css.cell.width,this._renderService.dimensions.css.cell.height,r)}getMouseReportCoords(e,t){const i=(0,o.getCoordsRelativeToElement)(window,e,t);if(this._charSizeService.hasValidSize)return i[0]=Math.min(Math.max(i[0],0),this._renderService.dimensions.css.canvas.width-1),i[1]=Math.min(Math.max(i[1],0),this._renderService.dimensions.css.canvas.height-1),{col:Math.floor(i[0]/this._renderService.dimensions.css.cell.width),row:Math.floor(i[1]/this._renderService.dimensions.css.cell.height),x:Math.floor(i[0]),y:Math.floor(i[1])}}};t.MouseService=a=s([r(0,n.IRenderService),r(1,n.ICharSizeService)],a)},3230:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.RenderService=void 0;const n=i(6193),o=i(4725),a=i(8460),h=i(844),c=i(7226),l=i(2585);let d=t.RenderService=class extends h.Disposable{get dimensions(){return this._renderer.value.dimensions}constructor(e,t,i,s,r,o,l,d){super(),this._rowCount=e,this._charSizeService=s,this._renderer=this.register(new h.MutableDisposable),this._pausedResizeTask=new c.DebouncedIdleTask,this._observerDisposable=this.register(new h.MutableDisposable),this._isPaused=!1,this._needsFullRefresh=!1,this._isNextRenderRedrawOnly=!0,this._needsSelectionRefresh=!1,this._canvasWidth=0,this._canvasHeight=0,this._selectionState={start:void 0,end:void 0,columnSelectMode:!1},this._onDimensionsChange=this.register(new a.EventEmitter),this.onDimensionsChange=this._onDimensionsChange.event,this._onRenderedViewportChange=this.register(new a.EventEmitter),this.onRenderedViewportChange=this._onRenderedViewportChange.event,this._onRender=this.register(new a.EventEmitter),this.onRender=this._onRender.event,this._onRefreshRequest=this.register(new a.EventEmitter),this.onRefreshRequest=this._onRefreshRequest.event,this._renderDebouncer=new n.RenderDebouncer(((e,t)=>this._renderRows(e,t)),l),this.register(this._renderDebouncer),this.register(l.onDprChange((()=>this.handleDevicePixelRatioChange()))),this.register(o.onResize((()=>this._fullRefresh()))),this.register(o.buffers.onBufferActivate((()=>this._renderer.value?.clear()))),this.register(i.onOptionChange((()=>this._handleOptionsChanged()))),this.register(this._charSizeService.onCharSizeChange((()=>this.handleCharSizeChanged()))),this.register(r.onDecorationRegistered((()=>this._fullRefresh()))),this.register(r.onDecorationRemoved((()=>this._fullRefresh()))),this.register(i.onMultipleOptionChange(["customGlyphs","drawBoldTextInBrightColors","letterSpacing","lineHeight","fontFamily","fontSize","fontWeight","fontWeightBold","minimumContrastRatio","rescaleOverlappingGlyphs"],(()=>{this.clear(),this.handleResize(o.cols,o.rows),this._fullRefresh()}))),this.register(i.onMultipleOptionChange(["cursorBlink","cursorStyle"],(()=>this.refreshRows(o.buffer.y,o.buffer.y,!0)))),this.register(d.onChangeColors((()=>this._fullRefresh()))),this._registerIntersectionObserver(l.window,t),this.register(l.onWindowChange((e=>this._registerIntersectionObserver(e,t))))}_registerIntersectionObserver(e,t){if("IntersectionObserver"in e){const i=new e.IntersectionObserver((e=>this._handleIntersectionChange(e[e.length-1])),{threshold:0});i.observe(t),this._observerDisposable.value=(0,h.toDisposable)((()=>i.disconnect()))}}_handleIntersectionChange(e){this._isPaused=void 0===e.isIntersecting?0===e.intersectionRatio:!e.isIntersecting,this._isPaused||this._charSizeService.hasValidSize||this._charSizeService.measure(),!this._isPaused&&this._needsFullRefresh&&(this._pausedResizeTask.flush(),this.refreshRows(0,this._rowCount-1),this._needsFullRefresh=!1)}refreshRows(e,t,i=!1){this._isPaused?this._needsFullRefresh=!0:(i||(this._isNextRenderRedrawOnly=!1),this._renderDebouncer.refresh(e,t,this._rowCount))}_renderRows(e,t){this._renderer.value&&(e=Math.min(e,this._rowCount-1),t=Math.min(t,this._rowCount-1),this._renderer.value.renderRows(e,t),this._needsSelectionRefresh&&(this._renderer.value.handleSelectionChanged(this._selectionState.start,this._selectionState.end,this._selectionState.columnSelectMode),this._needsSelectionRefresh=!1),this._isNextRenderRedrawOnly||this._onRenderedViewportChange.fire({start:e,end:t}),this._onRender.fire({start:e,end:t}),this._isNextRenderRedrawOnly=!0)}resize(e,t){this._rowCount=t,this._fireOnCanvasResize()}_handleOptionsChanged(){this._renderer.value&&(this.refreshRows(0,this._rowCount-1),this._fireOnCanvasResize())}_fireOnCanvasResize(){this._renderer.value&&(this._renderer.value.dimensions.css.canvas.width===this._canvasWidth&&this._renderer.value.dimensions.css.canvas.height===this._canvasHeight||this._onDimensionsChange.fire(this._renderer.value.dimensions))}hasRenderer(){return!!this._renderer.value}setRenderer(e){this._renderer.value=e,this._renderer.value&&(this._renderer.value.onRequestRedraw((e=>this.refreshRows(e.start,e.end,!0))),this._needsSelectionRefresh=!0,this._fullRefresh())}addRefreshCallback(e){return this._renderDebouncer.addRefreshCallback(e)}_fullRefresh(){this._isPaused?this._needsFullRefresh=!0:this.refreshRows(0,this._rowCount-1)}clearTextureAtlas(){this._renderer.value&&(this._renderer.value.clearTextureAtlas?.(),this._fullRefresh())}handleDevicePixelRatioChange(){this._charSizeService.measure(),this._renderer.value&&(this._renderer.value.handleDevicePixelRatioChange(),this.refreshRows(0,this._rowCount-1))}handleResize(e,t){this._renderer.value&&(this._isPaused?this._pausedResizeTask.set((()=>this._renderer.value?.handleResize(e,t))):this._renderer.value.handleResize(e,t),this._fullRefresh())}handleCharSizeChanged(){this._renderer.value?.handleCharSizeChanged()}handleBlur(){this._renderer.value?.handleBlur()}handleFocus(){this._renderer.value?.handleFocus()}handleSelectionChanged(e,t,i){this._selectionState.start=e,this._selectionState.end=t,this._selectionState.columnSelectMode=i,this._renderer.value?.handleSelectionChanged(e,t,i)}handleCursorMove(){this._renderer.value?.handleCursorMove()}clear(){this._renderer.value?.clear()}};t.RenderService=d=s([r(2,l.IOptionsService),r(3,o.ICharSizeService),r(4,l.IDecorationService),r(5,l.IBufferService),r(6,o.ICoreBrowserService),r(7,o.IThemeService)],d)},9312:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.SelectionService=void 0;const n=i(9806),o=i(9504),a=i(456),h=i(4725),c=i(8460),l=i(844),d=i(6114),_=i(4841),u=i(511),f=i(2585),v=String.fromCharCode(160),p=new RegExp(v,"g");let g=t.SelectionService=class extends l.Disposable{constructor(e,t,i,s,r,n,o,h,d){super(),this._element=e,this._screenElement=t,this._linkifier=i,this._bufferService=s,this._coreService=r,this._mouseService=n,this._optionsService=o,this._renderService=h,this._coreBrowserService=d,this._dragScrollAmount=0,this._enabled=!0,this._workCell=new u.CellData,this._mouseDownTimeStamp=0,this._oldHasSelection=!1,this._oldSelectionStart=void 0,this._oldSelectionEnd=void 0,this._onLinuxMouseSelection=this.register(new c.EventEmitter),this.onLinuxMouseSelection=this._onLinuxMouseSelection.event,this._onRedrawRequest=this.register(new c.EventEmitter),this.onRequestRedraw=this._onRedrawRequest.event,this._onSelectionChange=this.register(new c.EventEmitter),this.onSelectionChange=this._onSelectionChange.event,this._onRequestScrollLines=this.register(new c.EventEmitter),this.onRequestScrollLines=this._onRequestScrollLines.event,this._mouseMoveListener=e=>this._handleMouseMove(e),this._mouseUpListener=e=>this._handleMouseUp(e),this._coreService.onUserInput((()=>{this.hasSelection&&this.clearSelection()})),this._trimListener=this._bufferService.buffer.lines.onTrim((e=>this._handleTrim(e))),this.register(this._bufferService.buffers.onBufferActivate((e=>this._handleBufferActivate(e)))),this.enable(),this._model=new a.SelectionModel(this._bufferService),this._activeSelectionMode=0,this.register((0,l.toDisposable)((()=>{this._removeMouseDownListeners()})))}reset(){this.clearSelection()}disable(){this.clearSelection(),this._enabled=!1}enable(){this._enabled=!0}get selectionStart(){return this._model.finalSelectionStart}get selectionEnd(){return this._model.finalSelectionEnd}get hasSelection(){const e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;return!(!e||!t||e[0]===t[0]&&e[1]===t[1])}get selectionText(){const e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;if(!e||!t)return"";const i=this._bufferService.buffer,s=[];if(3===this._activeSelectionMode){if(e[0]===t[0])return"";const r=e[0]e.replace(p," "))).join(d.isWindows?"\r\n":"\n")}clearSelection(){this._model.clearSelection(),this._removeMouseDownListeners(),this.refresh(),this._onSelectionChange.fire()}refresh(e){this._refreshAnimationFrame||(this._refreshAnimationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._refresh()))),d.isLinux&&e&&this.selectionText.length&&this._onLinuxMouseSelection.fire(this.selectionText)}_refresh(){this._refreshAnimationFrame=void 0,this._onRedrawRequest.fire({start:this._model.finalSelectionStart,end:this._model.finalSelectionEnd,columnSelectMode:3===this._activeSelectionMode})}_isClickInSelection(e){const t=this._getMouseBufferCoords(e),i=this._model.finalSelectionStart,s=this._model.finalSelectionEnd;return!!(i&&s&&t)&&this._areCoordsInSelection(t,i,s)}isCellInSelection(e,t){const i=this._model.finalSelectionStart,s=this._model.finalSelectionEnd;return!(!i||!s)&&this._areCoordsInSelection([e,t],i,s)}_areCoordsInSelection(e,t,i){return e[1]>t[1]&&e[1]=t[0]&&e[0]=t[0]}_selectWordAtCursor(e,t){const i=this._linkifier.currentLink?.link?.range;if(i)return this._model.selectionStart=[i.start.x-1,i.start.y-1],this._model.selectionStartLength=(0,_.getRangeLength)(i,this._bufferService.cols),this._model.selectionEnd=void 0,!0;const s=this._getMouseBufferCoords(e);return!!s&&(this._selectWordAt(s,t),this._model.selectionEnd=void 0,!0)}selectAll(){this._model.isSelectAllActive=!0,this.refresh(),this._onSelectionChange.fire()}selectLines(e,t){this._model.clearSelection(),e=Math.max(e,0),t=Math.min(t,this._bufferService.buffer.lines.length-1),this._model.selectionStart=[0,e],this._model.selectionEnd=[this._bufferService.cols,t],this.refresh(),this._onSelectionChange.fire()}_handleTrim(e){this._model.handleTrim(e)&&this.refresh()}_getMouseBufferCoords(e){const t=this._mouseService.getCoords(e,this._screenElement,this._bufferService.cols,this._bufferService.rows,!0);if(t)return t[0]--,t[1]--,t[1]+=this._bufferService.buffer.ydisp,t}_getMouseEventScrollAmount(e){let t=(0,n.getCoordsRelativeToElement)(this._coreBrowserService.window,e,this._screenElement)[1];const i=this._renderService.dimensions.css.canvas.height;return t>=0&&t<=i?0:(t>i&&(t-=i),t=Math.min(Math.max(t,-50),50),t/=50,t/Math.abs(t)+Math.round(14*t))}shouldForceSelection(e){return d.isMac?e.altKey&&this._optionsService.rawOptions.macOptionClickForcesSelection:e.shiftKey}handleMouseDown(e){if(this._mouseDownTimeStamp=e.timeStamp,(2!==e.button||!this.hasSelection)&&0===e.button){if(!this._enabled){if(!this.shouldForceSelection(e))return;e.stopPropagation()}e.preventDefault(),this._dragScrollAmount=0,this._enabled&&e.shiftKey?this._handleIncrementalClick(e):1===e.detail?this._handleSingleClick(e):2===e.detail?this._handleDoubleClick(e):3===e.detail&&this._handleTripleClick(e),this._addMouseDownListeners(),this.refresh(!0)}}_addMouseDownListeners(){this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.addEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.addEventListener("mouseup",this._mouseUpListener)),this._dragScrollIntervalTimer=this._coreBrowserService.window.setInterval((()=>this._dragScroll()),50)}_removeMouseDownListeners(){this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.removeEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.removeEventListener("mouseup",this._mouseUpListener)),this._coreBrowserService.window.clearInterval(this._dragScrollIntervalTimer),this._dragScrollIntervalTimer=void 0}_handleIncrementalClick(e){this._model.selectionStart&&(this._model.selectionEnd=this._getMouseBufferCoords(e))}_handleSingleClick(e){if(this._model.selectionStartLength=0,this._model.isSelectAllActive=!1,this._activeSelectionMode=this.shouldColumnSelect(e)?3:0,this._model.selectionStart=this._getMouseBufferCoords(e),!this._model.selectionStart)return;this._model.selectionEnd=void 0;const t=this._bufferService.buffer.lines.get(this._model.selectionStart[1]);t&&t.length!==this._model.selectionStart[0]&&0===t.hasWidth(this._model.selectionStart[0])&&this._model.selectionStart[0]++}_handleDoubleClick(e){this._selectWordAtCursor(e,!0)&&(this._activeSelectionMode=1)}_handleTripleClick(e){const t=this._getMouseBufferCoords(e);t&&(this._activeSelectionMode=2,this._selectLineAt(t[1]))}shouldColumnSelect(e){return e.altKey&&!(d.isMac&&this._optionsService.rawOptions.macOptionClickForcesSelection)}_handleMouseMove(e){if(e.stopImmediatePropagation(),!this._model.selectionStart)return;const t=this._model.selectionEnd?[this._model.selectionEnd[0],this._model.selectionEnd[1]]:null;if(this._model.selectionEnd=this._getMouseBufferCoords(e),!this._model.selectionEnd)return void this.refresh(!0);2===this._activeSelectionMode?this._model.selectionEnd[1]0?this._model.selectionEnd[0]=this._bufferService.cols:this._dragScrollAmount<0&&(this._model.selectionEnd[0]=0));const i=this._bufferService.buffer;if(this._model.selectionEnd[1]0?(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=this._bufferService.cols),this._model.selectionEnd[1]=Math.min(e.ydisp+this._bufferService.rows,e.lines.length-1)):(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=0),this._model.selectionEnd[1]=e.ydisp),this.refresh()}}_handleMouseUp(e){const t=e.timeStamp-this._mouseDownTimeStamp;if(this._removeMouseDownListeners(),this.selectionText.length<=1&&t<500&&e.altKey&&this._optionsService.rawOptions.altClickMovesCursor){if(this._bufferService.buffer.ybase===this._bufferService.buffer.ydisp){const t=this._mouseService.getCoords(e,this._element,this._bufferService.cols,this._bufferService.rows,!1);if(t&&void 0!==t[0]&&void 0!==t[1]){const e=(0,o.moveToCellSequence)(t[0]-1,t[1]-1,this._bufferService,this._coreService.decPrivateModes.applicationCursorKeys);this._coreService.triggerDataEvent(e,!0)}}}else this._fireEventIfSelectionChanged()}_fireEventIfSelectionChanged(){const e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd,i=!(!e||!t||e[0]===t[0]&&e[1]===t[1]);i?e&&t&&(this._oldSelectionStart&&this._oldSelectionEnd&&e[0]===this._oldSelectionStart[0]&&e[1]===this._oldSelectionStart[1]&&t[0]===this._oldSelectionEnd[0]&&t[1]===this._oldSelectionEnd[1]||this._fireOnSelectionChange(e,t,i)):this._oldHasSelection&&this._fireOnSelectionChange(e,t,i)}_fireOnSelectionChange(e,t,i){this._oldSelectionStart=e,this._oldSelectionEnd=t,this._oldHasSelection=i,this._onSelectionChange.fire()}_handleBufferActivate(e){this.clearSelection(),this._trimListener.dispose(),this._trimListener=e.activeBuffer.lines.onTrim((e=>this._handleTrim(e)))}_convertViewportColToCharacterIndex(e,t){let i=t;for(let s=0;t>=s;s++){const r=e.loadCell(s,this._workCell).getChars().length;0===this._workCell.getWidth()?i--:r>1&&t!==s&&(i+=r-1)}return i}setSelection(e,t,i){this._model.clearSelection(),this._removeMouseDownListeners(),this._model.selectionStart=[e,t],this._model.selectionStartLength=i,this.refresh(),this._fireEventIfSelectionChanged()}rightClickSelect(e){this._isClickInSelection(e)||(this._selectWordAtCursor(e,!1)&&this.refresh(!0),this._fireEventIfSelectionChanged())}_getWordAt(e,t,i=!0,s=!0){if(e[0]>=this._bufferService.cols)return;const r=this._bufferService.buffer,n=r.lines.get(e[1]);if(!n)return;const o=r.translateBufferLineToString(e[1],!1);let a=this._convertViewportColToCharacterIndex(n,e[0]),h=a;const c=e[0]-a;let l=0,d=0,_=0,u=0;if(" "===o.charAt(a)){for(;a>0&&" "===o.charAt(a-1);)a--;for(;h1&&(u+=s-1,h+=s-1);t>0&&a>0&&!this._isCharWordSeparator(n.loadCell(t-1,this._workCell));){n.loadCell(t-1,this._workCell);const e=this._workCell.getChars().length;0===this._workCell.getWidth()?(l++,t--):e>1&&(_+=e-1,a-=e-1),a--,t--}for(;i1&&(u+=e-1,h+=e-1),h++,i++}}h++;let f=a+c-l+_,v=Math.min(this._bufferService.cols,h-a+l+d-_-u);if(t||""!==o.slice(a,h).trim()){if(i&&0===f&&32!==n.getCodePoint(0)){const t=r.lines.get(e[1]-1);if(t&&n.isWrapped&&32!==t.getCodePoint(this._bufferService.cols-1)){const t=this._getWordAt([this._bufferService.cols-1,e[1]-1],!1,!0,!1);if(t){const e=this._bufferService.cols-t.start;f-=e,v+=e}}}if(s&&f+v===this._bufferService.cols&&32!==n.getCodePoint(this._bufferService.cols-1)){const t=r.lines.get(e[1]+1);if(t?.isWrapped&&32!==t.getCodePoint(0)){const t=this._getWordAt([0,e[1]+1],!1,!1,!0);t&&(v+=t.length)}}return{start:f,length:v}}}_selectWordAt(e,t){const i=this._getWordAt(e,t);if(i){for(;i.start<0;)i.start+=this._bufferService.cols,e[1]--;this._model.selectionStart=[i.start,e[1]],this._model.selectionStartLength=i.length}}_selectToWordAt(e){const t=this._getWordAt(e,!0);if(t){let i=e[1];for(;t.start<0;)t.start+=this._bufferService.cols,i--;if(!this._model.areSelectionValuesReversed())for(;t.start+t.length>this._bufferService.cols;)t.length-=this._bufferService.cols,i++;this._model.selectionEnd=[this._model.areSelectionValuesReversed()?t.start:t.start+t.length,i]}}_isCharWordSeparator(e){return 0!==e.getWidth()&&this._optionsService.rawOptions.wordSeparator.indexOf(e.getChars())>=0}_selectLineAt(e){const t=this._bufferService.buffer.getWrappedRangeForLine(e),i={start:{x:0,y:t.first},end:{x:this._bufferService.cols-1,y:t.last}};this._model.selectionStart=[0,t.first],this._model.selectionEnd=void 0,this._model.selectionStartLength=(0,_.getRangeLength)(i,this._bufferService.cols)}};t.SelectionService=g=s([r(3,f.IBufferService),r(4,f.ICoreService),r(5,h.IMouseService),r(6,f.IOptionsService),r(7,h.IRenderService),r(8,h.ICoreBrowserService)],g)},4725:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ILinkProviderService=t.IThemeService=t.ICharacterJoinerService=t.ISelectionService=t.IRenderService=t.IMouseService=t.ICoreBrowserService=t.ICharSizeService=void 0;const s=i(8343);t.ICharSizeService=(0,s.createDecorator)("CharSizeService"),t.ICoreBrowserService=(0,s.createDecorator)("CoreBrowserService"),t.IMouseService=(0,s.createDecorator)("MouseService"),t.IRenderService=(0,s.createDecorator)("RenderService"),t.ISelectionService=(0,s.createDecorator)("SelectionService"),t.ICharacterJoinerService=(0,s.createDecorator)("CharacterJoinerService"),t.IThemeService=(0,s.createDecorator)("ThemeService"),t.ILinkProviderService=(0,s.createDecorator)("LinkProviderService")},6731:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.ThemeService=t.DEFAULT_ANSI_COLORS=void 0;const n=i(7239),o=i(8055),a=i(8460),h=i(844),c=i(2585),l=o.css.toColor("#ffffff"),d=o.css.toColor("#000000"),_=o.css.toColor("#ffffff"),u=o.css.toColor("#000000"),f={css:"rgba(255, 255, 255, 0.3)",rgba:4294967117};t.DEFAULT_ANSI_COLORS=Object.freeze((()=>{const e=[o.css.toColor("#2e3436"),o.css.toColor("#cc0000"),o.css.toColor("#4e9a06"),o.css.toColor("#c4a000"),o.css.toColor("#3465a4"),o.css.toColor("#75507b"),o.css.toColor("#06989a"),o.css.toColor("#d3d7cf"),o.css.toColor("#555753"),o.css.toColor("#ef2929"),o.css.toColor("#8ae234"),o.css.toColor("#fce94f"),o.css.toColor("#729fcf"),o.css.toColor("#ad7fa8"),o.css.toColor("#34e2e2"),o.css.toColor("#eeeeec")],t=[0,95,135,175,215,255];for(let i=0;i<216;i++){const s=t[i/36%6|0],r=t[i/6%6|0],n=t[i%6];e.push({css:o.channels.toCss(s,r,n),rgba:o.channels.toRgba(s,r,n)})}for(let t=0;t<24;t++){const i=8+10*t;e.push({css:o.channels.toCss(i,i,i),rgba:o.channels.toRgba(i,i,i)})}return e})());let v=t.ThemeService=class extends h.Disposable{get colors(){return this._colors}constructor(e){super(),this._optionsService=e,this._contrastCache=new n.ColorContrastCache,this._halfContrastCache=new n.ColorContrastCache,this._onChangeColors=this.register(new a.EventEmitter),this.onChangeColors=this._onChangeColors.event,this._colors={foreground:l,background:d,cursor:_,cursorAccent:u,selectionForeground:void 0,selectionBackgroundTransparent:f,selectionBackgroundOpaque:o.color.blend(d,f),selectionInactiveBackgroundTransparent:f,selectionInactiveBackgroundOpaque:o.color.blend(d,f),ansi:t.DEFAULT_ANSI_COLORS.slice(),contrastCache:this._contrastCache,halfContrastCache:this._halfContrastCache},this._updateRestoreColors(),this._setTheme(this._optionsService.rawOptions.theme),this.register(this._optionsService.onSpecificOptionChange("minimumContrastRatio",(()=>this._contrastCache.clear()))),this.register(this._optionsService.onSpecificOptionChange("theme",(()=>this._setTheme(this._optionsService.rawOptions.theme))))}_setTheme(e={}){const i=this._colors;if(i.foreground=p(e.foreground,l),i.background=p(e.background,d),i.cursor=p(e.cursor,_),i.cursorAccent=p(e.cursorAccent,u),i.selectionBackgroundTransparent=p(e.selectionBackground,f),i.selectionBackgroundOpaque=o.color.blend(i.background,i.selectionBackgroundTransparent),i.selectionInactiveBackgroundTransparent=p(e.selectionInactiveBackground,i.selectionBackgroundTransparent),i.selectionInactiveBackgroundOpaque=o.color.blend(i.background,i.selectionInactiveBackgroundTransparent),i.selectionForeground=e.selectionForeground?p(e.selectionForeground,o.NULL_COLOR):void 0,i.selectionForeground===o.NULL_COLOR&&(i.selectionForeground=void 0),o.color.isOpaque(i.selectionBackgroundTransparent)){const e=.3;i.selectionBackgroundTransparent=o.color.opacity(i.selectionBackgroundTransparent,e)}if(o.color.isOpaque(i.selectionInactiveBackgroundTransparent)){const e=.3;i.selectionInactiveBackgroundTransparent=o.color.opacity(i.selectionInactiveBackgroundTransparent,e)}if(i.ansi=t.DEFAULT_ANSI_COLORS.slice(),i.ansi[0]=p(e.black,t.DEFAULT_ANSI_COLORS[0]),i.ansi[1]=p(e.red,t.DEFAULT_ANSI_COLORS[1]),i.ansi[2]=p(e.green,t.DEFAULT_ANSI_COLORS[2]),i.ansi[3]=p(e.yellow,t.DEFAULT_ANSI_COLORS[3]),i.ansi[4]=p(e.blue,t.DEFAULT_ANSI_COLORS[4]),i.ansi[5]=p(e.magenta,t.DEFAULT_ANSI_COLORS[5]),i.ansi[6]=p(e.cyan,t.DEFAULT_ANSI_COLORS[6]),i.ansi[7]=p(e.white,t.DEFAULT_ANSI_COLORS[7]),i.ansi[8]=p(e.brightBlack,t.DEFAULT_ANSI_COLORS[8]),i.ansi[9]=p(e.brightRed,t.DEFAULT_ANSI_COLORS[9]),i.ansi[10]=p(e.brightGreen,t.DEFAULT_ANSI_COLORS[10]),i.ansi[11]=p(e.brightYellow,t.DEFAULT_ANSI_COLORS[11]),i.ansi[12]=p(e.brightBlue,t.DEFAULT_ANSI_COLORS[12]),i.ansi[13]=p(e.brightMagenta,t.DEFAULT_ANSI_COLORS[13]),i.ansi[14]=p(e.brightCyan,t.DEFAULT_ANSI_COLORS[14]),i.ansi[15]=p(e.brightWhite,t.DEFAULT_ANSI_COLORS[15]),e.extendedAnsi){const s=Math.min(i.ansi.length-16,e.extendedAnsi.length);for(let r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.CircularList=void 0;const s=i(8460),r=i(844);class n extends r.Disposable{constructor(e){super(),this._maxLength=e,this.onDeleteEmitter=this.register(new s.EventEmitter),this.onDelete=this.onDeleteEmitter.event,this.onInsertEmitter=this.register(new s.EventEmitter),this.onInsert=this.onInsertEmitter.event,this.onTrimEmitter=this.register(new s.EventEmitter),this.onTrim=this.onTrimEmitter.event,this._array=new Array(this._maxLength),this._startIndex=0,this._length=0}get maxLength(){return this._maxLength}set maxLength(e){if(this._maxLength===e)return;const t=new Array(e);for(let i=0;ithis._length)for(let t=this._length;t=e;t--)this._array[this._getCyclicIndex(t+i.length)]=this._array[this._getCyclicIndex(t)];for(let t=0;tthis._maxLength){const e=this._length+i.length-this._maxLength;this._startIndex+=e,this._length=this._maxLength,this.onTrimEmitter.fire(e)}else this._length+=i.length}trimStart(e){e>this._length&&(e=this._length),this._startIndex+=e,this._length-=e,this.onTrimEmitter.fire(e)}shiftElements(e,t,i){if(!(t<=0)){if(e<0||e>=this._length)throw new Error("start argument out of range");if(e+i<0)throw new Error("Cannot shift elements in list beyond index 0");if(i>0){for(let s=t-1;s>=0;s--)this.set(e+s+i,this.get(e+s));const s=e+t+i-this._length;if(s>0)for(this._length+=s;this._length>this._maxLength;)this._length--,this._startIndex++,this.onTrimEmitter.fire(1)}else for(let s=0;s{Object.defineProperty(t,"__esModule",{value:!0}),t.clone=void 0,t.clone=function e(t,i=5){if("object"!=typeof t)return t;const s=Array.isArray(t)?[]:{};for(const r in t)s[r]=i<=1?t[r]:t[r]&&e(t[r],i-1);return s}},8055:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.contrastRatio=t.toPaddedHex=t.rgba=t.rgb=t.css=t.color=t.channels=t.NULL_COLOR=void 0;let i=0,s=0,r=0,n=0;var o,a,h,c,l;function d(e){const t=e.toString(16);return t.length<2?"0"+t:t}function _(e,t){return e>>0},e.toColor=function(t,i,s,r){return{css:e.toCss(t,i,s,r),rgba:e.toRgba(t,i,s,r)}}}(o||(t.channels=o={})),function(e){function t(e,t){return n=Math.round(255*t),[i,s,r]=l.toChannels(e.rgba),{css:o.toCss(i,s,r,n),rgba:o.toRgba(i,s,r,n)}}e.blend=function(e,t){if(n=(255&t.rgba)/255,1===n)return{css:t.css,rgba:t.rgba};const a=t.rgba>>24&255,h=t.rgba>>16&255,c=t.rgba>>8&255,l=e.rgba>>24&255,d=e.rgba>>16&255,_=e.rgba>>8&255;return i=l+Math.round((a-l)*n),s=d+Math.round((h-d)*n),r=_+Math.round((c-_)*n),{css:o.toCss(i,s,r),rgba:o.toRgba(i,s,r)}},e.isOpaque=function(e){return 255==(255&e.rgba)},e.ensureContrastRatio=function(e,t,i){const s=l.ensureContrastRatio(e.rgba,t.rgba,i);if(s)return o.toColor(s>>24&255,s>>16&255,s>>8&255)},e.opaque=function(e){const t=(255|e.rgba)>>>0;return[i,s,r]=l.toChannels(t),{css:o.toCss(i,s,r),rgba:t}},e.opacity=t,e.multiplyOpacity=function(e,i){return n=255&e.rgba,t(e,n*i/255)},e.toColorRGB=function(e){return[e.rgba>>24&255,e.rgba>>16&255,e.rgba>>8&255]}}(a||(t.color=a={})),function(e){let t,a;try{const e=document.createElement("canvas");e.width=1,e.height=1;const i=e.getContext("2d",{willReadFrequently:!0});i&&(t=i,t.globalCompositeOperation="copy",a=t.createLinearGradient(0,0,1,1))}catch{}e.toColor=function(e){if(e.match(/#[\da-f]{3,8}/i))switch(e.length){case 4:return i=parseInt(e.slice(1,2).repeat(2),16),s=parseInt(e.slice(2,3).repeat(2),16),r=parseInt(e.slice(3,4).repeat(2),16),o.toColor(i,s,r);case 5:return i=parseInt(e.slice(1,2).repeat(2),16),s=parseInt(e.slice(2,3).repeat(2),16),r=parseInt(e.slice(3,4).repeat(2),16),n=parseInt(e.slice(4,5).repeat(2),16),o.toColor(i,s,r,n);case 7:return{css:e,rgba:(parseInt(e.slice(1),16)<<8|255)>>>0};case 9:return{css:e,rgba:parseInt(e.slice(1),16)>>>0}}const h=e.match(/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(,\s*(0|1|\d?\.(\d+))\s*)?\)/);if(h)return i=parseInt(h[1]),s=parseInt(h[2]),r=parseInt(h[3]),n=Math.round(255*(void 0===h[5]?1:parseFloat(h[5]))),o.toColor(i,s,r,n);if(!t||!a)throw new Error("css.toColor: Unsupported css format");if(t.fillStyle=a,t.fillStyle=e,"string"!=typeof t.fillStyle)throw new Error("css.toColor: Unsupported css format");if(t.fillRect(0,0,1,1),[i,s,r,n]=t.getImageData(0,0,1,1).data,255!==n)throw new Error("css.toColor: Unsupported css format");return{rgba:o.toRgba(i,s,r,n),css:e}}}(h||(t.css=h={})),function(e){function t(e,t,i){const s=e/255,r=t/255,n=i/255;return.2126*(s<=.03928?s/12.92:Math.pow((s+.055)/1.055,2.4))+.7152*(r<=.03928?r/12.92:Math.pow((r+.055)/1.055,2.4))+.0722*(n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4))}e.relativeLuminance=function(e){return t(e>>16&255,e>>8&255,255&e)},e.relativeLuminance2=t}(c||(t.rgb=c={})),function(e){function t(e,t,i){const s=e>>24&255,r=e>>16&255,n=e>>8&255;let o=t>>24&255,a=t>>16&255,h=t>>8&255,l=_(c.relativeLuminance2(o,a,h),c.relativeLuminance2(s,r,n));for(;l0||a>0||h>0);)o-=Math.max(0,Math.ceil(.1*o)),a-=Math.max(0,Math.ceil(.1*a)),h-=Math.max(0,Math.ceil(.1*h)),l=_(c.relativeLuminance2(o,a,h),c.relativeLuminance2(s,r,n));return(o<<24|a<<16|h<<8|255)>>>0}function a(e,t,i){const s=e>>24&255,r=e>>16&255,n=e>>8&255;let o=t>>24&255,a=t>>16&255,h=t>>8&255,l=_(c.relativeLuminance2(o,a,h),c.relativeLuminance2(s,r,n));for(;l>>0}e.blend=function(e,t){if(n=(255&t)/255,1===n)return t;const a=t>>24&255,h=t>>16&255,c=t>>8&255,l=e>>24&255,d=e>>16&255,_=e>>8&255;return i=l+Math.round((a-l)*n),s=d+Math.round((h-d)*n),r=_+Math.round((c-_)*n),o.toRgba(i,s,r)},e.ensureContrastRatio=function(e,i,s){const r=c.relativeLuminance(e>>8),n=c.relativeLuminance(i>>8);if(_(r,n)>8));if(o_(r,c.relativeLuminance(t>>8))?n:t}return n}const o=a(e,i,s),h=_(r,c.relativeLuminance(o>>8));if(h_(r,c.relativeLuminance(n>>8))?o:n}return o}},e.reduceLuminance=t,e.increaseLuminance=a,e.toChannels=function(e){return[e>>24&255,e>>16&255,e>>8&255,255&e]}}(l||(t.rgba=l={})),t.toPaddedHex=d,t.contrastRatio=_},8969:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CoreTerminal=void 0;const s=i(844),r=i(2585),n=i(4348),o=i(7866),a=i(744),h=i(7302),c=i(6975),l=i(8460),d=i(1753),_=i(1480),u=i(7994),f=i(9282),v=i(5435),p=i(5981),g=i(2660);let m=!1;class S extends s.Disposable{get onScroll(){return this._onScrollApi||(this._onScrollApi=this.register(new l.EventEmitter),this._onScroll.event((e=>{this._onScrollApi?.fire(e.position)}))),this._onScrollApi.event}get cols(){return this._bufferService.cols}get rows(){return this._bufferService.rows}get buffers(){return this._bufferService.buffers}get options(){return this.optionsService.options}set options(e){for(const t in e)this.optionsService.options[t]=e[t]}constructor(e){super(),this._windowsWrappingHeuristics=this.register(new s.MutableDisposable),this._onBinary=this.register(new l.EventEmitter),this.onBinary=this._onBinary.event,this._onData=this.register(new l.EventEmitter),this.onData=this._onData.event,this._onLineFeed=this.register(new l.EventEmitter),this.onLineFeed=this._onLineFeed.event,this._onResize=this.register(new l.EventEmitter),this.onResize=this._onResize.event,this._onWriteParsed=this.register(new l.EventEmitter),this.onWriteParsed=this._onWriteParsed.event,this._onScroll=this.register(new l.EventEmitter),this._instantiationService=new n.InstantiationService,this.optionsService=this.register(new h.OptionsService(e)),this._instantiationService.setService(r.IOptionsService,this.optionsService),this._bufferService=this.register(this._instantiationService.createInstance(a.BufferService)),this._instantiationService.setService(r.IBufferService,this._bufferService),this._logService=this.register(this._instantiationService.createInstance(o.LogService)),this._instantiationService.setService(r.ILogService,this._logService),this.coreService=this.register(this._instantiationService.createInstance(c.CoreService)),this._instantiationService.setService(r.ICoreService,this.coreService),this.coreMouseService=this.register(this._instantiationService.createInstance(d.CoreMouseService)),this._instantiationService.setService(r.ICoreMouseService,this.coreMouseService),this.unicodeService=this.register(this._instantiationService.createInstance(_.UnicodeService)),this._instantiationService.setService(r.IUnicodeService,this.unicodeService),this._charsetService=this._instantiationService.createInstance(u.CharsetService),this._instantiationService.setService(r.ICharsetService,this._charsetService),this._oscLinkService=this._instantiationService.createInstance(g.OscLinkService),this._instantiationService.setService(r.IOscLinkService,this._oscLinkService),this._inputHandler=this.register(new v.InputHandler(this._bufferService,this._charsetService,this.coreService,this._logService,this.optionsService,this._oscLinkService,this.coreMouseService,this.unicodeService)),this.register((0,l.forwardEvent)(this._inputHandler.onLineFeed,this._onLineFeed)),this.register(this._inputHandler),this.register((0,l.forwardEvent)(this._bufferService.onResize,this._onResize)),this.register((0,l.forwardEvent)(this.coreService.onData,this._onData)),this.register((0,l.forwardEvent)(this.coreService.onBinary,this._onBinary)),this.register(this.coreService.onRequestScrollToBottom((()=>this.scrollToBottom()))),this.register(this.coreService.onUserInput((()=>this._writeBuffer.handleUserInput()))),this.register(this.optionsService.onMultipleOptionChange(["windowsMode","windowsPty"],(()=>this._handleWindowsPtyOptionChange()))),this.register(this._bufferService.onScroll((e=>{this._onScroll.fire({position:this._bufferService.buffer.ydisp,source:0}),this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop,this._bufferService.buffer.scrollBottom)}))),this.register(this._inputHandler.onScroll((e=>{this._onScroll.fire({position:this._bufferService.buffer.ydisp,source:0}),this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop,this._bufferService.buffer.scrollBottom)}))),this._writeBuffer=this.register(new p.WriteBuffer(((e,t)=>this._inputHandler.parse(e,t)))),this.register((0,l.forwardEvent)(this._writeBuffer.onWriteParsed,this._onWriteParsed))}write(e,t){this._writeBuffer.write(e,t)}writeSync(e,t){this._logService.logLevel<=r.LogLevelEnum.WARN&&!m&&(this._logService.warn("writeSync is unreliable and will be removed soon."),m=!0),this._writeBuffer.writeSync(e,t)}input(e,t=!0){this.coreService.triggerDataEvent(e,t)}resize(e,t){isNaN(e)||isNaN(t)||(e=Math.max(e,a.MINIMUM_COLS),t=Math.max(t,a.MINIMUM_ROWS),this._bufferService.resize(e,t))}scroll(e,t=!1){this._bufferService.scroll(e,t)}scrollLines(e,t,i){this._bufferService.scrollLines(e,t,i)}scrollPages(e){this.scrollLines(e*(this.rows-1))}scrollToTop(){this.scrollLines(-this._bufferService.buffer.ydisp)}scrollToBottom(){this.scrollLines(this._bufferService.buffer.ybase-this._bufferService.buffer.ydisp)}scrollToLine(e){const t=e-this._bufferService.buffer.ydisp;0!==t&&this.scrollLines(t)}registerEscHandler(e,t){return this._inputHandler.registerEscHandler(e,t)}registerDcsHandler(e,t){return this._inputHandler.registerDcsHandler(e,t)}registerCsiHandler(e,t){return this._inputHandler.registerCsiHandler(e,t)}registerOscHandler(e,t){return this._inputHandler.registerOscHandler(e,t)}_setup(){this._handleWindowsPtyOptionChange()}reset(){this._inputHandler.reset(),this._bufferService.reset(),this._charsetService.reset(),this.coreService.reset(),this.coreMouseService.reset()}_handleWindowsPtyOptionChange(){let e=!1;const t=this.optionsService.rawOptions.windowsPty;t&&void 0!==t.buildNumber&&void 0!==t.buildNumber?e=!!("conpty"===t.backend&&t.buildNumber<21376):this.optionsService.rawOptions.windowsMode&&(e=!0),e?this._enableWindowsWrappingHeuristics():this._windowsWrappingHeuristics.clear()}_enableWindowsWrappingHeuristics(){if(!this._windowsWrappingHeuristics.value){const e=[];e.push(this.onLineFeed(f.updateWindowsModeWrappedState.bind(null,this._bufferService))),e.push(this.registerCsiHandler({final:"H"},(()=>((0,f.updateWindowsModeWrappedState)(this._bufferService),!1)))),this._windowsWrappingHeuristics.value=(0,s.toDisposable)((()=>{for(const t of e)t.dispose()}))}}}t.CoreTerminal=S},8460:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.runAndSubscribe=t.forwardEvent=t.EventEmitter=void 0,t.EventEmitter=class{constructor(){this._listeners=[],this._disposed=!1}get event(){return this._event||(this._event=e=>(this._listeners.push(e),{dispose:()=>{if(!this._disposed)for(let t=0;tt.fire(e)))},t.runAndSubscribe=function(e,t){return t(void 0),e((e=>t(e)))}},5435:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.InputHandler=t.WindowsOptionsReportType=void 0;const n=i(2584),o=i(7116),a=i(2015),h=i(844),c=i(482),l=i(8437),d=i(8460),_=i(643),u=i(511),f=i(3734),v=i(2585),p=i(1480),g=i(6242),m=i(6351),S=i(5941),C={"(":0,")":1,"*":2,"+":3,"-":1,".":2},b=131072;function w(e,t){if(e>24)return t.setWinLines||!1;switch(e){case 1:return!!t.restoreWin;case 2:return!!t.minimizeWin;case 3:return!!t.setWinPosition;case 4:return!!t.setWinSizePixels;case 5:return!!t.raiseWin;case 6:return!!t.lowerWin;case 7:return!!t.refreshWin;case 8:return!!t.setWinSizeChars;case 9:return!!t.maximizeWin;case 10:return!!t.fullscreenWin;case 11:return!!t.getWinState;case 13:return!!t.getWinPosition;case 14:return!!t.getWinSizePixels;case 15:return!!t.getScreenSizePixels;case 16:return!!t.getCellSizePixels;case 18:return!!t.getWinSizeChars;case 19:return!!t.getScreenSizeChars;case 20:return!!t.getIconTitle;case 21:return!!t.getWinTitle;case 22:return!!t.pushTitle;case 23:return!!t.popTitle;case 24:return!!t.setWinLines}return!1}var y;!function(e){e[e.GET_WIN_SIZE_PIXELS=0]="GET_WIN_SIZE_PIXELS",e[e.GET_CELL_SIZE_PIXELS=1]="GET_CELL_SIZE_PIXELS"}(y||(t.WindowsOptionsReportType=y={}));let E=0;class k extends h.Disposable{getAttrData(){return this._curAttrData}constructor(e,t,i,s,r,h,_,f,v=new a.EscapeSequenceParser){super(),this._bufferService=e,this._charsetService=t,this._coreService=i,this._logService=s,this._optionsService=r,this._oscLinkService=h,this._coreMouseService=_,this._unicodeService=f,this._parser=v,this._parseBuffer=new Uint32Array(4096),this._stringDecoder=new c.StringToUtf32,this._utf8Decoder=new c.Utf8ToUtf32,this._workCell=new u.CellData,this._windowTitle="",this._iconName="",this._windowTitleStack=[],this._iconNameStack=[],this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._eraseAttrDataInternal=l.DEFAULT_ATTR_DATA.clone(),this._onRequestBell=this.register(new d.EventEmitter),this.onRequestBell=this._onRequestBell.event,this._onRequestRefreshRows=this.register(new d.EventEmitter),this.onRequestRefreshRows=this._onRequestRefreshRows.event,this._onRequestReset=this.register(new d.EventEmitter),this.onRequestReset=this._onRequestReset.event,this._onRequestSendFocus=this.register(new d.EventEmitter),this.onRequestSendFocus=this._onRequestSendFocus.event,this._onRequestSyncScrollBar=this.register(new d.EventEmitter),this.onRequestSyncScrollBar=this._onRequestSyncScrollBar.event,this._onRequestWindowsOptionsReport=this.register(new d.EventEmitter),this.onRequestWindowsOptionsReport=this._onRequestWindowsOptionsReport.event,this._onA11yChar=this.register(new d.EventEmitter),this.onA11yChar=this._onA11yChar.event,this._onA11yTab=this.register(new d.EventEmitter),this.onA11yTab=this._onA11yTab.event,this._onCursorMove=this.register(new d.EventEmitter),this.onCursorMove=this._onCursorMove.event,this._onLineFeed=this.register(new d.EventEmitter),this.onLineFeed=this._onLineFeed.event,this._onScroll=this.register(new d.EventEmitter),this.onScroll=this._onScroll.event,this._onTitleChange=this.register(new d.EventEmitter),this.onTitleChange=this._onTitleChange.event,this._onColor=this.register(new d.EventEmitter),this.onColor=this._onColor.event,this._parseStack={paused:!1,cursorStartX:0,cursorStartY:0,decodedLength:0,position:0},this._specialColors=[256,257,258],this.register(this._parser),this._dirtyRowTracker=new L(this._bufferService),this._activeBuffer=this._bufferService.buffer,this.register(this._bufferService.buffers.onBufferActivate((e=>this._activeBuffer=e.activeBuffer))),this._parser.setCsiHandlerFallback(((e,t)=>{this._logService.debug("Unknown CSI code: ",{identifier:this._parser.identToString(e),params:t.toArray()})})),this._parser.setEscHandlerFallback((e=>{this._logService.debug("Unknown ESC code: ",{identifier:this._parser.identToString(e)})})),this._parser.setExecuteHandlerFallback((e=>{this._logService.debug("Unknown EXECUTE code: ",{code:e})})),this._parser.setOscHandlerFallback(((e,t,i)=>{this._logService.debug("Unknown OSC code: ",{identifier:e,action:t,data:i})})),this._parser.setDcsHandlerFallback(((e,t,i)=>{"HOOK"===t&&(i=i.toArray()),this._logService.debug("Unknown DCS code: ",{identifier:this._parser.identToString(e),action:t,payload:i})})),this._parser.setPrintHandler(((e,t,i)=>this.print(e,t,i))),this._parser.registerCsiHandler({final:"@"},(e=>this.insertChars(e))),this._parser.registerCsiHandler({intermediates:" ",final:"@"},(e=>this.scrollLeft(e))),this._parser.registerCsiHandler({final:"A"},(e=>this.cursorUp(e))),this._parser.registerCsiHandler({intermediates:" ",final:"A"},(e=>this.scrollRight(e))),this._parser.registerCsiHandler({final:"B"},(e=>this.cursorDown(e))),this._parser.registerCsiHandler({final:"C"},(e=>this.cursorForward(e))),this._parser.registerCsiHandler({final:"D"},(e=>this.cursorBackward(e))),this._parser.registerCsiHandler({final:"E"},(e=>this.cursorNextLine(e))),this._parser.registerCsiHandler({final:"F"},(e=>this.cursorPrecedingLine(e))),this._parser.registerCsiHandler({final:"G"},(e=>this.cursorCharAbsolute(e))),this._parser.registerCsiHandler({final:"H"},(e=>this.cursorPosition(e))),this._parser.registerCsiHandler({final:"I"},(e=>this.cursorForwardTab(e))),this._parser.registerCsiHandler({final:"J"},(e=>this.eraseInDisplay(e,!1))),this._parser.registerCsiHandler({prefix:"?",final:"J"},(e=>this.eraseInDisplay(e,!0))),this._parser.registerCsiHandler({final:"K"},(e=>this.eraseInLine(e,!1))),this._parser.registerCsiHandler({prefix:"?",final:"K"},(e=>this.eraseInLine(e,!0))),this._parser.registerCsiHandler({final:"L"},(e=>this.insertLines(e))),this._parser.registerCsiHandler({final:"M"},(e=>this.deleteLines(e))),this._parser.registerCsiHandler({final:"P"},(e=>this.deleteChars(e))),this._parser.registerCsiHandler({final:"S"},(e=>this.scrollUp(e))),this._parser.registerCsiHandler({final:"T"},(e=>this.scrollDown(e))),this._parser.registerCsiHandler({final:"X"},(e=>this.eraseChars(e))),this._parser.registerCsiHandler({final:"Z"},(e=>this.cursorBackwardTab(e))),this._parser.registerCsiHandler({final:"`"},(e=>this.charPosAbsolute(e))),this._parser.registerCsiHandler({final:"a"},(e=>this.hPositionRelative(e))),this._parser.registerCsiHandler({final:"b"},(e=>this.repeatPrecedingCharacter(e))),this._parser.registerCsiHandler({final:"c"},(e=>this.sendDeviceAttributesPrimary(e))),this._parser.registerCsiHandler({prefix:">",final:"c"},(e=>this.sendDeviceAttributesSecondary(e))),this._parser.registerCsiHandler({final:"d"},(e=>this.linePosAbsolute(e))),this._parser.registerCsiHandler({final:"e"},(e=>this.vPositionRelative(e))),this._parser.registerCsiHandler({final:"f"},(e=>this.hVPosition(e))),this._parser.registerCsiHandler({final:"g"},(e=>this.tabClear(e))),this._parser.registerCsiHandler({final:"h"},(e=>this.setMode(e))),this._parser.registerCsiHandler({prefix:"?",final:"h"},(e=>this.setModePrivate(e))),this._parser.registerCsiHandler({final:"l"},(e=>this.resetMode(e))),this._parser.registerCsiHandler({prefix:"?",final:"l"},(e=>this.resetModePrivate(e))),this._parser.registerCsiHandler({final:"m"},(e=>this.charAttributes(e))),this._parser.registerCsiHandler({final:"n"},(e=>this.deviceStatus(e))),this._parser.registerCsiHandler({prefix:"?",final:"n"},(e=>this.deviceStatusPrivate(e))),this._parser.registerCsiHandler({intermediates:"!",final:"p"},(e=>this.softReset(e))),this._parser.registerCsiHandler({intermediates:" ",final:"q"},(e=>this.setCursorStyle(e))),this._parser.registerCsiHandler({final:"r"},(e=>this.setScrollRegion(e))),this._parser.registerCsiHandler({final:"s"},(e=>this.saveCursor(e))),this._parser.registerCsiHandler({final:"t"},(e=>this.windowOptions(e))),this._parser.registerCsiHandler({final:"u"},(e=>this.restoreCursor(e))),this._parser.registerCsiHandler({intermediates:"'",final:"}"},(e=>this.insertColumns(e))),this._parser.registerCsiHandler({intermediates:"'",final:"~"},(e=>this.deleteColumns(e))),this._parser.registerCsiHandler({intermediates:'"',final:"q"},(e=>this.selectProtected(e))),this._parser.registerCsiHandler({intermediates:"$",final:"p"},(e=>this.requestMode(e,!0))),this._parser.registerCsiHandler({prefix:"?",intermediates:"$",final:"p"},(e=>this.requestMode(e,!1))),this._parser.setExecuteHandler(n.C0.BEL,(()=>this.bell())),this._parser.setExecuteHandler(n.C0.LF,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.VT,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.FF,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.CR,(()=>this.carriageReturn())),this._parser.setExecuteHandler(n.C0.BS,(()=>this.backspace())),this._parser.setExecuteHandler(n.C0.HT,(()=>this.tab())),this._parser.setExecuteHandler(n.C0.SO,(()=>this.shiftOut())),this._parser.setExecuteHandler(n.C0.SI,(()=>this.shiftIn())),this._parser.setExecuteHandler(n.C1.IND,(()=>this.index())),this._parser.setExecuteHandler(n.C1.NEL,(()=>this.nextLine())),this._parser.setExecuteHandler(n.C1.HTS,(()=>this.tabSet())),this._parser.registerOscHandler(0,new g.OscHandler((e=>(this.setTitle(e),this.setIconName(e),!0)))),this._parser.registerOscHandler(1,new g.OscHandler((e=>this.setIconName(e)))),this._parser.registerOscHandler(2,new g.OscHandler((e=>this.setTitle(e)))),this._parser.registerOscHandler(4,new g.OscHandler((e=>this.setOrReportIndexedColor(e)))),this._parser.registerOscHandler(8,new g.OscHandler((e=>this.setHyperlink(e)))),this._parser.registerOscHandler(10,new g.OscHandler((e=>this.setOrReportFgColor(e)))),this._parser.registerOscHandler(11,new g.OscHandler((e=>this.setOrReportBgColor(e)))),this._parser.registerOscHandler(12,new g.OscHandler((e=>this.setOrReportCursorColor(e)))),this._parser.registerOscHandler(104,new g.OscHandler((e=>this.restoreIndexedColor(e)))),this._parser.registerOscHandler(110,new g.OscHandler((e=>this.restoreFgColor(e)))),this._parser.registerOscHandler(111,new g.OscHandler((e=>this.restoreBgColor(e)))),this._parser.registerOscHandler(112,new g.OscHandler((e=>this.restoreCursorColor(e)))),this._parser.registerEscHandler({final:"7"},(()=>this.saveCursor())),this._parser.registerEscHandler({final:"8"},(()=>this.restoreCursor())),this._parser.registerEscHandler({final:"D"},(()=>this.index())),this._parser.registerEscHandler({final:"E"},(()=>this.nextLine())),this._parser.registerEscHandler({final:"H"},(()=>this.tabSet())),this._parser.registerEscHandler({final:"M"},(()=>this.reverseIndex())),this._parser.registerEscHandler({final:"="},(()=>this.keypadApplicationMode())),this._parser.registerEscHandler({final:">"},(()=>this.keypadNumericMode())),this._parser.registerEscHandler({final:"c"},(()=>this.fullReset())),this._parser.registerEscHandler({final:"n"},(()=>this.setgLevel(2))),this._parser.registerEscHandler({final:"o"},(()=>this.setgLevel(3))),this._parser.registerEscHandler({final:"|"},(()=>this.setgLevel(3))),this._parser.registerEscHandler({final:"}"},(()=>this.setgLevel(2))),this._parser.registerEscHandler({final:"~"},(()=>this.setgLevel(1))),this._parser.registerEscHandler({intermediates:"%",final:"@"},(()=>this.selectDefaultCharset())),this._parser.registerEscHandler({intermediates:"%",final:"G"},(()=>this.selectDefaultCharset()));for(const e in o.CHARSETS)this._parser.registerEscHandler({intermediates:"(",final:e},(()=>this.selectCharset("("+e))),this._parser.registerEscHandler({intermediates:")",final:e},(()=>this.selectCharset(")"+e))),this._parser.registerEscHandler({intermediates:"*",final:e},(()=>this.selectCharset("*"+e))),this._parser.registerEscHandler({intermediates:"+",final:e},(()=>this.selectCharset("+"+e))),this._parser.registerEscHandler({intermediates:"-",final:e},(()=>this.selectCharset("-"+e))),this._parser.registerEscHandler({intermediates:".",final:e},(()=>this.selectCharset("."+e))),this._parser.registerEscHandler({intermediates:"/",final:e},(()=>this.selectCharset("/"+e)));this._parser.registerEscHandler({intermediates:"#",final:"8"},(()=>this.screenAlignmentPattern())),this._parser.setErrorHandler((e=>(this._logService.error("Parsing error: ",e),e))),this._parser.registerDcsHandler({intermediates:"$",final:"q"},new m.DcsHandler(((e,t)=>this.requestStatusString(e,t))))}_preserveStack(e,t,i,s){this._parseStack.paused=!0,this._parseStack.cursorStartX=e,this._parseStack.cursorStartY=t,this._parseStack.decodedLength=i,this._parseStack.position=s}_logSlowResolvingAsync(e){this._logService.logLevel<=v.LogLevelEnum.WARN&&Promise.race([e,new Promise(((e,t)=>setTimeout((()=>t("#SLOW_TIMEOUT")),5e3)))]).catch((e=>{if("#SLOW_TIMEOUT"!==e)throw e;console.warn("async parser handler taking longer than 5000 ms")}))}_getCurrentLinkId(){return this._curAttrData.extended.urlId}parse(e,t){let i,s=this._activeBuffer.x,r=this._activeBuffer.y,n=0;const o=this._parseStack.paused;if(o){if(i=this._parser.parse(this._parseBuffer,this._parseStack.decodedLength,t))return this._logSlowResolvingAsync(i),i;s=this._parseStack.cursorStartX,r=this._parseStack.cursorStartY,this._parseStack.paused=!1,e.length>b&&(n=this._parseStack.position+b)}if(this._logService.logLevel<=v.LogLevelEnum.DEBUG&&this._logService.debug("parsing data"+("string"==typeof e?` "${e}"`:` "${Array.prototype.map.call(e,(e=>String.fromCharCode(e))).join("")}"`),"string"==typeof e?e.split("").map((e=>e.charCodeAt(0))):e),this._parseBuffer.lengthb)for(let t=n;t0&&2===f.getWidth(this._activeBuffer.x-1)&&f.setCellFromCodepoint(this._activeBuffer.x-1,0,1,u);let v=this._parser.precedingJoinState;for(let g=t;ga)if(h){const e=f;let t=this._activeBuffer.x-m;for(this._activeBuffer.x=m,this._activeBuffer.y++,this._activeBuffer.y===this._activeBuffer.scrollBottom+1?(this._activeBuffer.y--,this._bufferService.scroll(this._eraseAttrData(),!0)):(this._activeBuffer.y>=this._bufferService.rows&&(this._activeBuffer.y=this._bufferService.rows-1),this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!0),f=this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y),m>0&&f instanceof l.BufferLine&&f.copyCellsFrom(e,t,0,m,!1);t=0;)f.setCellFromCodepoint(this._activeBuffer.x++,0,0,u)}else if(d&&(f.insertCells(this._activeBuffer.x,r-m,this._activeBuffer.getNullCell(u)),2===f.getWidth(a-1)&&f.setCellFromCodepoint(a-1,_.NULL_CELL_CODE,_.NULL_CELL_WIDTH,u)),f.setCellFromCodepoint(this._activeBuffer.x++,s,r,u),r>0)for(;--r;)f.setCellFromCodepoint(this._activeBuffer.x++,0,0,u)}this._parser.precedingJoinState=v,this._activeBuffer.x0&&0===f.getWidth(this._activeBuffer.x)&&!f.hasContent(this._activeBuffer.x)&&f.setCellFromCodepoint(this._activeBuffer.x,0,1,u),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}registerCsiHandler(e,t){return"t"!==e.final||e.prefix||e.intermediates?this._parser.registerCsiHandler(e,t):this._parser.registerCsiHandler(e,(e=>!w(e.params[0],this._optionsService.rawOptions.windowOptions)||t(e)))}registerDcsHandler(e,t){return this._parser.registerDcsHandler(e,new m.DcsHandler(t))}registerEscHandler(e,t){return this._parser.registerEscHandler(e,t)}registerOscHandler(e,t){return this._parser.registerOscHandler(e,new g.OscHandler(t))}bell(){return this._onRequestBell.fire(),!0}lineFeed(){return this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._optionsService.rawOptions.convertEol&&(this._activeBuffer.x=0),this._activeBuffer.y++,this._activeBuffer.y===this._activeBuffer.scrollBottom+1?(this._activeBuffer.y--,this._bufferService.scroll(this._eraseAttrData())):this._activeBuffer.y>=this._bufferService.rows?this._activeBuffer.y=this._bufferService.rows-1:this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!1,this._activeBuffer.x>=this._bufferService.cols&&this._activeBuffer.x--,this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._onLineFeed.fire(),!0}carriageReturn(){return this._activeBuffer.x=0,!0}backspace(){if(!this._coreService.decPrivateModes.reverseWraparound)return this._restrictCursor(),this._activeBuffer.x>0&&this._activeBuffer.x--,!0;if(this._restrictCursor(this._bufferService.cols),this._activeBuffer.x>0)this._activeBuffer.x--;else if(0===this._activeBuffer.x&&this._activeBuffer.y>this._activeBuffer.scrollTop&&this._activeBuffer.y<=this._activeBuffer.scrollBottom&&this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y)?.isWrapped){this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!1,this._activeBuffer.y--,this._activeBuffer.x=this._bufferService.cols-1;const e=this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y);e.hasWidth(this._activeBuffer.x)&&!e.hasContent(this._activeBuffer.x)&&this._activeBuffer.x--}return this._restrictCursor(),!0}tab(){if(this._activeBuffer.x>=this._bufferService.cols)return!0;const e=this._activeBuffer.x;return this._activeBuffer.x=this._activeBuffer.nextStop(),this._optionsService.rawOptions.screenReaderMode&&this._onA11yTab.fire(this._activeBuffer.x-e),!0}shiftOut(){return this._charsetService.setgLevel(1),!0}shiftIn(){return this._charsetService.setgLevel(0),!0}_restrictCursor(e=this._bufferService.cols-1){this._activeBuffer.x=Math.min(e,Math.max(0,this._activeBuffer.x)),this._activeBuffer.y=this._coreService.decPrivateModes.origin?Math.min(this._activeBuffer.scrollBottom,Math.max(this._activeBuffer.scrollTop,this._activeBuffer.y)):Math.min(this._bufferService.rows-1,Math.max(0,this._activeBuffer.y)),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}_setCursor(e,t){this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._coreService.decPrivateModes.origin?(this._activeBuffer.x=e,this._activeBuffer.y=this._activeBuffer.scrollTop+t):(this._activeBuffer.x=e,this._activeBuffer.y=t),this._restrictCursor(),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}_moveCursor(e,t){this._restrictCursor(),this._setCursor(this._activeBuffer.x+e,this._activeBuffer.y+t)}cursorUp(e){const t=this._activeBuffer.y-this._activeBuffer.scrollTop;return t>=0?this._moveCursor(0,-Math.min(t,e.params[0]||1)):this._moveCursor(0,-(e.params[0]||1)),!0}cursorDown(e){const t=this._activeBuffer.scrollBottom-this._activeBuffer.y;return t>=0?this._moveCursor(0,Math.min(t,e.params[0]||1)):this._moveCursor(0,e.params[0]||1),!0}cursorForward(e){return this._moveCursor(e.params[0]||1,0),!0}cursorBackward(e){return this._moveCursor(-(e.params[0]||1),0),!0}cursorNextLine(e){return this.cursorDown(e),this._activeBuffer.x=0,!0}cursorPrecedingLine(e){return this.cursorUp(e),this._activeBuffer.x=0,!0}cursorCharAbsolute(e){return this._setCursor((e.params[0]||1)-1,this._activeBuffer.y),!0}cursorPosition(e){return this._setCursor(e.length>=2?(e.params[1]||1)-1:0,(e.params[0]||1)-1),!0}charPosAbsolute(e){return this._setCursor((e.params[0]||1)-1,this._activeBuffer.y),!0}hPositionRelative(e){return this._moveCursor(e.params[0]||1,0),!0}linePosAbsolute(e){return this._setCursor(this._activeBuffer.x,(e.params[0]||1)-1),!0}vPositionRelative(e){return this._moveCursor(0,e.params[0]||1),!0}hVPosition(e){return this.cursorPosition(e),!0}tabClear(e){const t=e.params[0];return 0===t?delete this._activeBuffer.tabs[this._activeBuffer.x]:3===t&&(this._activeBuffer.tabs={}),!0}cursorForwardTab(e){if(this._activeBuffer.x>=this._bufferService.cols)return!0;let t=e.params[0]||1;for(;t--;)this._activeBuffer.x=this._activeBuffer.nextStop();return!0}cursorBackwardTab(e){if(this._activeBuffer.x>=this._bufferService.cols)return!0;let t=e.params[0]||1;for(;t--;)this._activeBuffer.x=this._activeBuffer.prevStop();return!0}selectProtected(e){const t=e.params[0];return 1===t&&(this._curAttrData.bg|=536870912),2!==t&&0!==t||(this._curAttrData.bg&=-536870913),!0}_eraseInBufferLine(e,t,i,s=!1,r=!1){const n=this._activeBuffer.lines.get(this._activeBuffer.ybase+e);n.replaceCells(t,i,this._activeBuffer.getNullCell(this._eraseAttrData()),r),s&&(n.isWrapped=!1)}_resetBufferLine(e,t=!1){const i=this._activeBuffer.lines.get(this._activeBuffer.ybase+e);i&&(i.fill(this._activeBuffer.getNullCell(this._eraseAttrData()),t),this._bufferService.buffer.clearMarkers(this._activeBuffer.ybase+e),i.isWrapped=!1)}eraseInDisplay(e,t=!1){let i;switch(this._restrictCursor(this._bufferService.cols),e.params[0]){case 0:for(i=this._activeBuffer.y,this._dirtyRowTracker.markDirty(i),this._eraseInBufferLine(i++,this._activeBuffer.x,this._bufferService.cols,0===this._activeBuffer.x,t);i=this._bufferService.cols&&(this._activeBuffer.lines.get(i+1).isWrapped=!1);i--;)this._resetBufferLine(i,t);this._dirtyRowTracker.markDirty(0);break;case 2:for(i=this._bufferService.rows,this._dirtyRowTracker.markDirty(i-1);i--;)this._resetBufferLine(i,t);this._dirtyRowTracker.markDirty(0);break;case 3:const e=this._activeBuffer.lines.length-this._bufferService.rows;e>0&&(this._activeBuffer.lines.trimStart(e),this._activeBuffer.ybase=Math.max(this._activeBuffer.ybase-e,0),this._activeBuffer.ydisp=Math.max(this._activeBuffer.ydisp-e,0),this._onScroll.fire(0))}return!0}eraseInLine(e,t=!1){switch(this._restrictCursor(this._bufferService.cols),e.params[0]){case 0:this._eraseInBufferLine(this._activeBuffer.y,this._activeBuffer.x,this._bufferService.cols,0===this._activeBuffer.x,t);break;case 1:this._eraseInBufferLine(this._activeBuffer.y,0,this._activeBuffer.x+1,!1,t);break;case 2:this._eraseInBufferLine(this._activeBuffer.y,0,this._bufferService.cols,!0,t)}return this._dirtyRowTracker.markDirty(this._activeBuffer.y),!0}insertLines(e){this._restrictCursor();let t=e.params[0]||1;if(this._activeBuffer.y>this._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.y65535?2:1}let h=a;for(let e=1;e0||(this._is("xterm")||this._is("rxvt-unicode")||this._is("screen")?this._coreService.triggerDataEvent(n.C0.ESC+"[?1;2c"):this._is("linux")&&this._coreService.triggerDataEvent(n.C0.ESC+"[?6c")),!0}sendDeviceAttributesSecondary(e){return e.params[0]>0||(this._is("xterm")?this._coreService.triggerDataEvent(n.C0.ESC+"[>0;276;0c"):this._is("rxvt-unicode")?this._coreService.triggerDataEvent(n.C0.ESC+"[>85;95;0c"):this._is("linux")?this._coreService.triggerDataEvent(e.params[0]+"c"):this._is("screen")&&this._coreService.triggerDataEvent(n.C0.ESC+"[>83;40003;0c")),!0}_is(e){return 0===(this._optionsService.rawOptions.termName+"").indexOf(e)}setMode(e){for(let t=0;te?1:2,u=e.params[0];return f=u,v=t?2===u?4:4===u?_(o.modes.insertMode):12===u?3:20===u?_(d.convertEol):0:1===u?_(i.applicationCursorKeys):3===u?d.windowOptions.setWinLines?80===h?2:132===h?1:0:0:6===u?_(i.origin):7===u?_(i.wraparound):8===u?3:9===u?_("X10"===s):12===u?_(d.cursorBlink):25===u?_(!o.isCursorHidden):45===u?_(i.reverseWraparound):66===u?_(i.applicationKeypad):67===u?4:1e3===u?_("VT200"===s):1002===u?_("DRAG"===s):1003===u?_("ANY"===s):1004===u?_(i.sendFocus):1005===u?4:1006===u?_("SGR"===r):1015===u?4:1016===u?_("SGR_PIXELS"===r):1048===u?1:47===u||1047===u||1049===u?_(c===l):2004===u?_(i.bracketedPasteMode):0,o.triggerDataEvent(`${n.C0.ESC}[${t?"":"?"}${f};${v}$y`),!0;var f,v}_updateAttrColor(e,t,i,s,r){return 2===t?(e|=50331648,e&=-16777216,e|=f.AttributeData.fromColorRGB([i,s,r])):5===t&&(e&=-50331904,e|=33554432|255&i),e}_extractColor(e,t,i){const s=[0,0,-1,0,0,0];let r=0,n=0;do{if(s[n+r]=e.params[t+n],e.hasSubParams(t+n)){const i=e.getSubParams(t+n);let o=0;do{5===s[1]&&(r=1),s[n+o+1+r]=i[o]}while(++o=2||2===s[1]&&n+r>=5)break;s[1]&&(r=1)}while(++n+t5)&&(e=1),t.extended.underlineStyle=e,t.fg|=268435456,0===e&&(t.fg&=-268435457),t.updateExtended()}_processSGR0(e){e.fg=l.DEFAULT_ATTR_DATA.fg,e.bg=l.DEFAULT_ATTR_DATA.bg,e.extended=e.extended.clone(),e.extended.underlineStyle=0,e.extended.underlineColor&=-67108864,e.updateExtended()}charAttributes(e){if(1===e.length&&0===e.params[0])return this._processSGR0(this._curAttrData),!0;const t=e.length;let i;const s=this._curAttrData;for(let r=0;r=30&&i<=37?(s.fg&=-50331904,s.fg|=16777216|i-30):i>=40&&i<=47?(s.bg&=-50331904,s.bg|=16777216|i-40):i>=90&&i<=97?(s.fg&=-50331904,s.fg|=16777224|i-90):i>=100&&i<=107?(s.bg&=-50331904,s.bg|=16777224|i-100):0===i?this._processSGR0(s):1===i?s.fg|=134217728:3===i?s.bg|=67108864:4===i?(s.fg|=268435456,this._processUnderline(e.hasSubParams(r)?e.getSubParams(r)[0]:1,s)):5===i?s.fg|=536870912:7===i?s.fg|=67108864:8===i?s.fg|=1073741824:9===i?s.fg|=2147483648:2===i?s.bg|=134217728:21===i?this._processUnderline(2,s):22===i?(s.fg&=-134217729,s.bg&=-134217729):23===i?s.bg&=-67108865:24===i?(s.fg&=-268435457,this._processUnderline(0,s)):25===i?s.fg&=-536870913:27===i?s.fg&=-67108865:28===i?s.fg&=-1073741825:29===i?s.fg&=2147483647:39===i?(s.fg&=-67108864,s.fg|=16777215&l.DEFAULT_ATTR_DATA.fg):49===i?(s.bg&=-67108864,s.bg|=16777215&l.DEFAULT_ATTR_DATA.bg):38===i||48===i||58===i?r+=this._extractColor(e,r,s):53===i?s.bg|=1073741824:55===i?s.bg&=-1073741825:59===i?(s.extended=s.extended.clone(),s.extended.underlineColor=-1,s.updateExtended()):100===i?(s.fg&=-67108864,s.fg|=16777215&l.DEFAULT_ATTR_DATA.fg,s.bg&=-67108864,s.bg|=16777215&l.DEFAULT_ATTR_DATA.bg):this._logService.debug("Unknown SGR attribute: %d.",i);return!0}deviceStatus(e){switch(e.params[0]){case 5:this._coreService.triggerDataEvent(`${n.C0.ESC}[0n`);break;case 6:const e=this._activeBuffer.y+1,t=this._activeBuffer.x+1;this._coreService.triggerDataEvent(`${n.C0.ESC}[${e};${t}R`)}return!0}deviceStatusPrivate(e){if(6===e.params[0]){const e=this._activeBuffer.y+1,t=this._activeBuffer.x+1;this._coreService.triggerDataEvent(`${n.C0.ESC}[?${e};${t}R`)}return!0}softReset(e){return this._coreService.isCursorHidden=!1,this._onRequestSyncScrollBar.fire(),this._activeBuffer.scrollTop=0,this._activeBuffer.scrollBottom=this._bufferService.rows-1,this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._coreService.reset(),this._charsetService.reset(),this._activeBuffer.savedX=0,this._activeBuffer.savedY=this._activeBuffer.ybase,this._activeBuffer.savedCurAttrData.fg=this._curAttrData.fg,this._activeBuffer.savedCurAttrData.bg=this._curAttrData.bg,this._activeBuffer.savedCharset=this._charsetService.charset,this._coreService.decPrivateModes.origin=!1,!0}setCursorStyle(e){const t=e.params[0]||1;switch(t){case 1:case 2:this._optionsService.options.cursorStyle="block";break;case 3:case 4:this._optionsService.options.cursorStyle="underline";break;case 5:case 6:this._optionsService.options.cursorStyle="bar"}const i=t%2==1;return this._optionsService.options.cursorBlink=i,!0}setScrollRegion(e){const t=e.params[0]||1;let i;return(e.length<2||(i=e.params[1])>this._bufferService.rows||0===i)&&(i=this._bufferService.rows),i>t&&(this._activeBuffer.scrollTop=t-1,this._activeBuffer.scrollBottom=i-1,this._setCursor(0,0)),!0}windowOptions(e){if(!w(e.params[0],this._optionsService.rawOptions.windowOptions))return!0;const t=e.length>1?e.params[1]:0;switch(e.params[0]){case 14:2!==t&&this._onRequestWindowsOptionsReport.fire(y.GET_WIN_SIZE_PIXELS);break;case 16:this._onRequestWindowsOptionsReport.fire(y.GET_CELL_SIZE_PIXELS);break;case 18:this._bufferService&&this._coreService.triggerDataEvent(`${n.C0.ESC}[8;${this._bufferService.rows};${this._bufferService.cols}t`);break;case 22:0!==t&&2!==t||(this._windowTitleStack.push(this._windowTitle),this._windowTitleStack.length>10&&this._windowTitleStack.shift()),0!==t&&1!==t||(this._iconNameStack.push(this._iconName),this._iconNameStack.length>10&&this._iconNameStack.shift());break;case 23:0!==t&&2!==t||this._windowTitleStack.length&&this.setTitle(this._windowTitleStack.pop()),0!==t&&1!==t||this._iconNameStack.length&&this.setIconName(this._iconNameStack.pop())}return!0}saveCursor(e){return this._activeBuffer.savedX=this._activeBuffer.x,this._activeBuffer.savedY=this._activeBuffer.ybase+this._activeBuffer.y,this._activeBuffer.savedCurAttrData.fg=this._curAttrData.fg,this._activeBuffer.savedCurAttrData.bg=this._curAttrData.bg,this._activeBuffer.savedCharset=this._charsetService.charset,!0}restoreCursor(e){return this._activeBuffer.x=this._activeBuffer.savedX||0,this._activeBuffer.y=Math.max(this._activeBuffer.savedY-this._activeBuffer.ybase,0),this._curAttrData.fg=this._activeBuffer.savedCurAttrData.fg,this._curAttrData.bg=this._activeBuffer.savedCurAttrData.bg,this._charsetService.charset=this._savedCharset,this._activeBuffer.savedCharset&&(this._charsetService.charset=this._activeBuffer.savedCharset),this._restrictCursor(),!0}setTitle(e){return this._windowTitle=e,this._onTitleChange.fire(e),!0}setIconName(e){return this._iconName=e,!0}setOrReportIndexedColor(e){const t=[],i=e.split(";");for(;i.length>1;){const e=i.shift(),s=i.shift();if(/^\d+$/.exec(e)){const i=parseInt(e);if(D(i))if("?"===s)t.push({type:0,index:i});else{const e=(0,S.parseColor)(s);e&&t.push({type:1,index:i,color:e})}}}return t.length&&this._onColor.fire(t),!0}setHyperlink(e){const t=e.split(";");return!(t.length<2)&&(t[1]?this._createHyperlink(t[0],t[1]):!t[0]&&this._finishHyperlink())}_createHyperlink(e,t){this._getCurrentLinkId()&&this._finishHyperlink();const i=e.split(":");let s;const r=i.findIndex((e=>e.startsWith("id=")));return-1!==r&&(s=i[r].slice(3)||void 0),this._curAttrData.extended=this._curAttrData.extended.clone(),this._curAttrData.extended.urlId=this._oscLinkService.registerLink({id:s,uri:t}),this._curAttrData.updateExtended(),!0}_finishHyperlink(){return this._curAttrData.extended=this._curAttrData.extended.clone(),this._curAttrData.extended.urlId=0,this._curAttrData.updateExtended(),!0}_setOrReportSpecialColor(e,t){const i=e.split(";");for(let e=0;e=this._specialColors.length);++e,++t)if("?"===i[e])this._onColor.fire([{type:0,index:this._specialColors[t]}]);else{const s=(0,S.parseColor)(i[e]);s&&this._onColor.fire([{type:1,index:this._specialColors[t],color:s}])}return!0}setOrReportFgColor(e){return this._setOrReportSpecialColor(e,0)}setOrReportBgColor(e){return this._setOrReportSpecialColor(e,1)}setOrReportCursorColor(e){return this._setOrReportSpecialColor(e,2)}restoreIndexedColor(e){if(!e)return this._onColor.fire([{type:2}]),!0;const t=[],i=e.split(";");for(let e=0;e=this._bufferService.rows&&(this._activeBuffer.y=this._bufferService.rows-1),this._restrictCursor(),!0}tabSet(){return this._activeBuffer.tabs[this._activeBuffer.x]=!0,!0}reverseIndex(){if(this._restrictCursor(),this._activeBuffer.y===this._activeBuffer.scrollTop){const e=this._activeBuffer.scrollBottom-this._activeBuffer.scrollTop;this._activeBuffer.lines.shiftElements(this._activeBuffer.ybase+this._activeBuffer.y,e,1),this._activeBuffer.lines.set(this._activeBuffer.ybase+this._activeBuffer.y,this._activeBuffer.getBlankLine(this._eraseAttrData())),this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop,this._activeBuffer.scrollBottom)}else this._activeBuffer.y--,this._restrictCursor();return!0}fullReset(){return this._parser.reset(),this._onRequestReset.fire(),!0}reset(){this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._eraseAttrDataInternal=l.DEFAULT_ATTR_DATA.clone()}_eraseAttrData(){return this._eraseAttrDataInternal.bg&=-67108864,this._eraseAttrDataInternal.bg|=67108863&this._curAttrData.bg,this._eraseAttrDataInternal}setgLevel(e){return this._charsetService.setgLevel(e),!0}screenAlignmentPattern(){const e=new u.CellData;e.content=1<<22|"E".charCodeAt(0),e.fg=this._curAttrData.fg,e.bg=this._curAttrData.bg,this._setCursor(0,0);for(let t=0;t(this._coreService.triggerDataEvent(`${n.C0.ESC}${e}${n.C0.ESC}\\`),!0))('"q'===e?`P1$r${this._curAttrData.isProtected()?1:0}"q`:'"p'===e?'P1$r61;1"p':"r"===e?`P1$r${i.scrollTop+1};${i.scrollBottom+1}r`:"m"===e?"P1$r0m":" q"===e?`P1$r${{block:2,underline:4,bar:6}[s.cursorStyle]-(s.cursorBlink?1:0)} q`:"P0$r")}markRangeDirty(e,t){this._dirtyRowTracker.markRangeDirty(e,t)}}t.InputHandler=k;let L=class{constructor(e){this._bufferService=e,this.clearRange()}clearRange(){this.start=this._bufferService.buffer.y,this.end=this._bufferService.buffer.y}markDirty(e){ethis.end&&(this.end=e)}markRangeDirty(e,t){e>t&&(E=e,e=t,t=E),ethis.end&&(this.end=t)}markAllDirty(){this.markRangeDirty(0,this._bufferService.rows-1)}};function D(e){return 0<=e&&e<256}L=s([r(0,v.IBufferService)],L)},844:(e,t)=>{function i(e){for(const t of e)t.dispose();e.length=0}Object.defineProperty(t,"__esModule",{value:!0}),t.getDisposeArrayDisposable=t.disposeArray=t.toDisposable=t.MutableDisposable=t.Disposable=void 0,t.Disposable=class{constructor(){this._disposables=[],this._isDisposed=!1}dispose(){this._isDisposed=!0;for(const e of this._disposables)e.dispose();this._disposables.length=0}register(e){return this._disposables.push(e),e}unregister(e){const t=this._disposables.indexOf(e);-1!==t&&this._disposables.splice(t,1)}},t.MutableDisposable=class{constructor(){this._isDisposed=!1}get value(){return this._isDisposed?void 0:this._value}set value(e){this._isDisposed||e===this._value||(this._value?.dispose(),this._value=e)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,this._value?.dispose(),this._value=void 0}},t.toDisposable=function(e){return{dispose:e}},t.disposeArray=i,t.getDisposeArrayDisposable=function(e){return{dispose:()=>i(e)}}},1505:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.FourKeyMap=t.TwoKeyMap=void 0;class i{constructor(){this._data={}}set(e,t,i){this._data[e]||(this._data[e]={}),this._data[e][t]=i}get(e,t){return this._data[e]?this._data[e][t]:void 0}clear(){this._data={}}}t.TwoKeyMap=i,t.FourKeyMap=class{constructor(){this._data=new i}set(e,t,s,r,n){this._data.get(e,t)||this._data.set(e,t,new i),this._data.get(e,t).set(s,r,n)}get(e,t,i,s){return this._data.get(e,t)?.get(i,s)}clear(){this._data.clear()}}},6114:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.isChromeOS=t.isLinux=t.isWindows=t.isIphone=t.isIpad=t.isMac=t.getSafariVersion=t.isSafari=t.isLegacyEdge=t.isFirefox=t.isNode=void 0,t.isNode="undefined"!=typeof process&&"title"in process;const i=t.isNode?"node":navigator.userAgent,s=t.isNode?"node":navigator.platform;t.isFirefox=i.includes("Firefox"),t.isLegacyEdge=i.includes("Edge"),t.isSafari=/^((?!chrome|android).)*safari/i.test(i),t.getSafariVersion=function(){if(!t.isSafari)return 0;const e=i.match(/Version\/(\d+)/);return null===e||e.length<2?0:parseInt(e[1])},t.isMac=["Macintosh","MacIntel","MacPPC","Mac68K"].includes(s),t.isIpad="iPad"===s,t.isIphone="iPhone"===s,t.isWindows=["Windows","Win16","Win32","WinCE"].includes(s),t.isLinux=s.indexOf("Linux")>=0,t.isChromeOS=/\bCrOS\b/.test(i)},6106:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SortedList=void 0;let i=0;t.SortedList=class{constructor(e){this._getKey=e,this._array=[]}clear(){this._array.length=0}insert(e){0!==this._array.length?(i=this._search(this._getKey(e)),this._array.splice(i,0,e)):this._array.push(e)}delete(e){if(0===this._array.length)return!1;const t=this._getKey(e);if(void 0===t)return!1;if(i=this._search(t),-1===i)return!1;if(this._getKey(this._array[i])!==t)return!1;do{if(this._array[i]===e)return this._array.splice(i,1),!0}while(++i=this._array.length)&&this._getKey(this._array[i])===e))do{yield this._array[i]}while(++i=this._array.length)&&this._getKey(this._array[i])===e))do{t(this._array[i])}while(++i=t;){let s=t+i>>1;const r=this._getKey(this._array[s]);if(r>e)i=s-1;else{if(!(r0&&this._getKey(this._array[s-1])===e;)s--;return s}t=s+1}}return t}}},7226:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DebouncedIdleTask=t.IdleTaskQueue=t.PriorityTaskQueue=void 0;const s=i(6114);class r{constructor(){this._tasks=[],this._i=0}enqueue(e){this._tasks.push(e),this._start()}flush(){for(;this._ir)return s-t<-20&&console.warn(`task queue exceeded allotted deadline by ${Math.abs(Math.round(s-t))}ms`),void this._start();s=r}this.clear()}}class n extends r{_requestCallback(e){return setTimeout((()=>e(this._createDeadline(16))))}_cancelCallback(e){clearTimeout(e)}_createDeadline(e){const t=Date.now()+e;return{timeRemaining:()=>Math.max(0,t-Date.now())}}}t.PriorityTaskQueue=n,t.IdleTaskQueue=!s.isNode&&"requestIdleCallback"in window?class extends r{_requestCallback(e){return requestIdleCallback(e)}_cancelCallback(e){cancelIdleCallback(e)}}:n,t.DebouncedIdleTask=class{constructor(){this._queue=new t.IdleTaskQueue}set(e){this._queue.clear(),this._queue.enqueue(e)}flush(){this._queue.flush()}}},9282:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.updateWindowsModeWrappedState=void 0;const s=i(643);t.updateWindowsModeWrappedState=function(e){const t=e.buffer.lines.get(e.buffer.ybase+e.buffer.y-1),i=t?.get(e.cols-1),r=e.buffer.lines.get(e.buffer.ybase+e.buffer.y);r&&i&&(r.isWrapped=i[s.CHAR_DATA_CODE_INDEX]!==s.NULL_CELL_CODE&&i[s.CHAR_DATA_CODE_INDEX]!==s.WHITESPACE_CELL_CODE)}},3734:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ExtendedAttrs=t.AttributeData=void 0;class i{constructor(){this.fg=0,this.bg=0,this.extended=new s}static toColorRGB(e){return[e>>>16&255,e>>>8&255,255&e]}static fromColorRGB(e){return(255&e[0])<<16|(255&e[1])<<8|255&e[2]}clone(){const e=new i;return e.fg=this.fg,e.bg=this.bg,e.extended=this.extended.clone(),e}isInverse(){return 67108864&this.fg}isBold(){return 134217728&this.fg}isUnderline(){return this.hasExtendedAttrs()&&0!==this.extended.underlineStyle?1:268435456&this.fg}isBlink(){return 536870912&this.fg}isInvisible(){return 1073741824&this.fg}isItalic(){return 67108864&this.bg}isDim(){return 134217728&this.bg}isStrikethrough(){return 2147483648&this.fg}isProtected(){return 536870912&this.bg}isOverline(){return 1073741824&this.bg}getFgColorMode(){return 50331648&this.fg}getBgColorMode(){return 50331648&this.bg}isFgRGB(){return 50331648==(50331648&this.fg)}isBgRGB(){return 50331648==(50331648&this.bg)}isFgPalette(){return 16777216==(50331648&this.fg)||33554432==(50331648&this.fg)}isBgPalette(){return 16777216==(50331648&this.bg)||33554432==(50331648&this.bg)}isFgDefault(){return 0==(50331648&this.fg)}isBgDefault(){return 0==(50331648&this.bg)}isAttributeDefault(){return 0===this.fg&&0===this.bg}getFgColor(){switch(50331648&this.fg){case 16777216:case 33554432:return 255&this.fg;case 50331648:return 16777215&this.fg;default:return-1}}getBgColor(){switch(50331648&this.bg){case 16777216:case 33554432:return 255&this.bg;case 50331648:return 16777215&this.bg;default:return-1}}hasExtendedAttrs(){return 268435456&this.bg}updateExtended(){this.extended.isEmpty()?this.bg&=-268435457:this.bg|=268435456}getUnderlineColor(){if(268435456&this.bg&&~this.extended.underlineColor)switch(50331648&this.extended.underlineColor){case 16777216:case 33554432:return 255&this.extended.underlineColor;case 50331648:return 16777215&this.extended.underlineColor;default:return this.getFgColor()}return this.getFgColor()}getUnderlineColorMode(){return 268435456&this.bg&&~this.extended.underlineColor?50331648&this.extended.underlineColor:this.getFgColorMode()}isUnderlineColorRGB(){return 268435456&this.bg&&~this.extended.underlineColor?50331648==(50331648&this.extended.underlineColor):this.isFgRGB()}isUnderlineColorPalette(){return 268435456&this.bg&&~this.extended.underlineColor?16777216==(50331648&this.extended.underlineColor)||33554432==(50331648&this.extended.underlineColor):this.isFgPalette()}isUnderlineColorDefault(){return 268435456&this.bg&&~this.extended.underlineColor?0==(50331648&this.extended.underlineColor):this.isFgDefault()}getUnderlineStyle(){return 268435456&this.fg?268435456&this.bg?this.extended.underlineStyle:1:0}getUnderlineVariantOffset(){return this.extended.underlineVariantOffset}}t.AttributeData=i;class s{get ext(){return this._urlId?-469762049&this._ext|this.underlineStyle<<26:this._ext}set ext(e){this._ext=e}get underlineStyle(){return this._urlId?5:(469762048&this._ext)>>26}set underlineStyle(e){this._ext&=-469762049,this._ext|=e<<26&469762048}get underlineColor(){return 67108863&this._ext}set underlineColor(e){this._ext&=-67108864,this._ext|=67108863&e}get urlId(){return this._urlId}set urlId(e){this._urlId=e}get underlineVariantOffset(){const e=(3758096384&this._ext)>>29;return e<0?4294967288^e:e}set underlineVariantOffset(e){this._ext&=536870911,this._ext|=e<<29&3758096384}constructor(e=0,t=0){this._ext=0,this._urlId=0,this._ext=e,this._urlId=t}clone(){return new s(this._ext,this._urlId)}isEmpty(){return 0===this.underlineStyle&&0===this._urlId}}t.ExtendedAttrs=s},9092:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Buffer=t.MAX_BUFFER_SIZE=void 0;const s=i(6349),r=i(7226),n=i(3734),o=i(8437),a=i(4634),h=i(511),c=i(643),l=i(4863),d=i(7116);t.MAX_BUFFER_SIZE=4294967295,t.Buffer=class{constructor(e,t,i){this._hasScrollback=e,this._optionsService=t,this._bufferService=i,this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.tabs={},this.savedY=0,this.savedX=0,this.savedCurAttrData=o.DEFAULT_ATTR_DATA.clone(),this.savedCharset=d.DEFAULT_CHARSET,this.markers=[],this._nullCell=h.CellData.fromCharData([0,c.NULL_CELL_CHAR,c.NULL_CELL_WIDTH,c.NULL_CELL_CODE]),this._whitespaceCell=h.CellData.fromCharData([0,c.WHITESPACE_CELL_CHAR,c.WHITESPACE_CELL_WIDTH,c.WHITESPACE_CELL_CODE]),this._isClearing=!1,this._memoryCleanupQueue=new r.IdleTaskQueue,this._memoryCleanupPosition=0,this._cols=this._bufferService.cols,this._rows=this._bufferService.rows,this.lines=new s.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}getNullCell(e){return e?(this._nullCell.fg=e.fg,this._nullCell.bg=e.bg,this._nullCell.extended=e.extended):(this._nullCell.fg=0,this._nullCell.bg=0,this._nullCell.extended=new n.ExtendedAttrs),this._nullCell}getWhitespaceCell(e){return e?(this._whitespaceCell.fg=e.fg,this._whitespaceCell.bg=e.bg,this._whitespaceCell.extended=e.extended):(this._whitespaceCell.fg=0,this._whitespaceCell.bg=0,this._whitespaceCell.extended=new n.ExtendedAttrs),this._whitespaceCell}getBlankLine(e,t){return new o.BufferLine(this._bufferService.cols,this.getNullCell(e),t)}get hasScrollback(){return this._hasScrollback&&this.lines.maxLength>this._rows}get isCursorInViewport(){const e=this.ybase+this.y-this.ydisp;return e>=0&&et.MAX_BUFFER_SIZE?t.MAX_BUFFER_SIZE:i}fillViewportRows(e){if(0===this.lines.length){void 0===e&&(e=o.DEFAULT_ATTR_DATA);let t=this._rows;for(;t--;)this.lines.push(this.getBlankLine(e))}}clear(){this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.lines=new s.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}resize(e,t){const i=this.getNullCell(o.DEFAULT_ATTR_DATA);let s=0;const r=this._getCorrectBufferLength(t);if(r>this.lines.maxLength&&(this.lines.maxLength=r),this.lines.length>0){if(this._cols0&&this.lines.length<=this.ybase+this.y+n+1?(this.ybase--,n++,this.ydisp>0&&this.ydisp--):this.lines.push(new o.BufferLine(e,i)));else for(let e=this._rows;e>t;e--)this.lines.length>t+this.ybase&&(this.lines.length>this.ybase+this.y+1?this.lines.pop():(this.ybase++,this.ydisp++));if(r0&&(this.lines.trimStart(e),this.ybase=Math.max(this.ybase-e,0),this.ydisp=Math.max(this.ydisp-e,0),this.savedY=Math.max(this.savedY-e,0)),this.lines.maxLength=r}this.x=Math.min(this.x,e-1),this.y=Math.min(this.y,t-1),n&&(this.y+=n),this.savedX=Math.min(this.savedX,e-1),this.scrollTop=0}if(this.scrollBottom=t-1,this._isReflowEnabled&&(this._reflow(e,t),this._cols>e))for(let t=0;t.1*this.lines.length&&(this._memoryCleanupPosition=0,this._memoryCleanupQueue.enqueue((()=>this._batchedMemoryCleanup())))}_batchedMemoryCleanup(){let e=!0;this._memoryCleanupPosition>=this.lines.length&&(this._memoryCleanupPosition=0,e=!1);let t=0;for(;this._memoryCleanupPosition100)return!0;return e}get _isReflowEnabled(){const e=this._optionsService.rawOptions.windowsPty;return e&&e.buildNumber?this._hasScrollback&&"conpty"===e.backend&&e.buildNumber>=21376:this._hasScrollback&&!this._optionsService.rawOptions.windowsMode}_reflow(e,t){this._cols!==e&&(e>this._cols?this._reflowLarger(e,t):this._reflowSmaller(e,t))}_reflowLarger(e,t){const i=(0,a.reflowLargerGetLinesToRemove)(this.lines,this._cols,e,this.ybase+this.y,this.getNullCell(o.DEFAULT_ATTR_DATA));if(i.length>0){const s=(0,a.reflowLargerCreateNewLayout)(this.lines,i);(0,a.reflowLargerApplyNewLayout)(this.lines,s.layout),this._reflowLargerAdjustViewport(e,t,s.countRemoved)}}_reflowLargerAdjustViewport(e,t,i){const s=this.getNullCell(o.DEFAULT_ATTR_DATA);let r=i;for(;r-- >0;)0===this.ybase?(this.y>0&&this.y--,this.lines.length=0;n--){let h=this.lines.get(n);if(!h||!h.isWrapped&&h.getTrimmedLength()<=e)continue;const c=[h];for(;h.isWrapped&&n>0;)h=this.lines.get(--n),c.unshift(h);const l=this.ybase+this.y;if(l>=n&&l0&&(s.push({start:n+c.length+r,newLines:v}),r+=v.length),c.push(...v);let p=_.length-1,g=_[p];0===g&&(p--,g=_[p]);let m=c.length-u-1,S=d;for(;m>=0;){const e=Math.min(S,g);if(void 0===c[p])break;if(c[p].copyCellsFrom(c[m],S-e,g-e,e,!0),g-=e,0===g&&(p--,g=_[p]),S-=e,0===S){m--;const e=Math.max(m,0);S=(0,a.getWrappedLineTrimmedLength)(c,e,this._cols)}}for(let t=0;t0;)0===this.ybase?this.y0){const e=[],t=[];for(let e=0;e=0;c--)if(a&&a.start>n+h){for(let e=a.newLines.length-1;e>=0;e--)this.lines.set(c--,a.newLines[e]);c++,e.push({index:n+1,amount:a.newLines.length}),h+=a.newLines.length,a=s[++o]}else this.lines.set(c,t[n--]);let c=0;for(let t=e.length-1;t>=0;t--)e[t].index+=c,this.lines.onInsertEmitter.fire(e[t]),c+=e[t].amount;const l=Math.max(0,i+r-this.lines.maxLength);l>0&&this.lines.onTrimEmitter.fire(l)}}translateBufferLineToString(e,t,i=0,s){const r=this.lines.get(e);return r?r.translateToString(t,i,s):""}getWrappedRangeForLine(e){let t=e,i=e;for(;t>0&&this.lines.get(t).isWrapped;)t--;for(;i+10;);return e>=this._cols?this._cols-1:e<0?0:e}nextStop(e){for(null==e&&(e=this.x);!this.tabs[++e]&&e=this._cols?this._cols-1:e<0?0:e}clearMarkers(e){this._isClearing=!0;for(let t=0;t{t.line-=e,t.line<0&&t.dispose()}))),t.register(this.lines.onInsert((e=>{t.line>=e.index&&(t.line+=e.amount)}))),t.register(this.lines.onDelete((e=>{t.line>=e.index&&t.linee.index&&(t.line-=e.amount)}))),t.register(t.onDispose((()=>this._removeMarker(t)))),t}_removeMarker(e){this._isClearing||this.markers.splice(this.markers.indexOf(e),1)}}},8437:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferLine=t.DEFAULT_ATTR_DATA=void 0;const s=i(3734),r=i(511),n=i(643),o=i(482);t.DEFAULT_ATTR_DATA=Object.freeze(new s.AttributeData);let a=0;class h{constructor(e,t,i=!1){this.isWrapped=i,this._combined={},this._extendedAttrs={},this._data=new Uint32Array(3*e);const s=t||r.CellData.fromCharData([0,n.NULL_CELL_CHAR,n.NULL_CELL_WIDTH,n.NULL_CELL_CODE]);for(let t=0;t>22,2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):i]}set(e,t){this._data[3*e+1]=t[n.CHAR_DATA_ATTR_INDEX],t[n.CHAR_DATA_CHAR_INDEX].length>1?(this._combined[e]=t[1],this._data[3*e+0]=2097152|e|t[n.CHAR_DATA_WIDTH_INDEX]<<22):this._data[3*e+0]=t[n.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|t[n.CHAR_DATA_WIDTH_INDEX]<<22}getWidth(e){return this._data[3*e+0]>>22}hasWidth(e){return 12582912&this._data[3*e+0]}getFg(e){return this._data[3*e+1]}getBg(e){return this._data[3*e+2]}hasContent(e){return 4194303&this._data[3*e+0]}getCodePoint(e){const t=this._data[3*e+0];return 2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):2097151&t}isCombined(e){return 2097152&this._data[3*e+0]}getString(e){const t=this._data[3*e+0];return 2097152&t?this._combined[e]:2097151&t?(0,o.stringFromCodePoint)(2097151&t):""}isProtected(e){return 536870912&this._data[3*e+2]}loadCell(e,t){return a=3*e,t.content=this._data[a+0],t.fg=this._data[a+1],t.bg=this._data[a+2],2097152&t.content&&(t.combinedData=this._combined[e]),268435456&t.bg&&(t.extended=this._extendedAttrs[e]),t}setCell(e,t){2097152&t.content&&(this._combined[e]=t.combinedData),268435456&t.bg&&(this._extendedAttrs[e]=t.extended),this._data[3*e+0]=t.content,this._data[3*e+1]=t.fg,this._data[3*e+2]=t.bg}setCellFromCodepoint(e,t,i,s){268435456&s.bg&&(this._extendedAttrs[e]=s.extended),this._data[3*e+0]=t|i<<22,this._data[3*e+1]=s.fg,this._data[3*e+2]=s.bg}addCodepointToCell(e,t,i){let s=this._data[3*e+0];2097152&s?this._combined[e]+=(0,o.stringFromCodePoint)(t):2097151&s?(this._combined[e]=(0,o.stringFromCodePoint)(2097151&s)+(0,o.stringFromCodePoint)(t),s&=-2097152,s|=2097152):s=t|1<<22,i&&(s&=-12582913,s|=i<<22),this._data[3*e+0]=s}insertCells(e,t,i){if((e%=this.length)&&2===this.getWidth(e-1)&&this.setCellFromCodepoint(e-1,0,1,i),t=0;--i)this.setCell(e+t+i,this.loadCell(e+i,s));for(let s=0;sthis.length){if(this._data.buffer.byteLength>=4*i)this._data=new Uint32Array(this._data.buffer,0,i);else{const e=new Uint32Array(i);e.set(this._data),this._data=e}for(let i=this.length;i=e&&delete this._combined[s]}const s=Object.keys(this._extendedAttrs);for(let t=0;t=e&&delete this._extendedAttrs[i]}}return this.length=e,4*i*2=0;--e)if(4194303&this._data[3*e+0])return e+(this._data[3*e+0]>>22);return 0}getNoBgTrimmedLength(){for(let e=this.length-1;e>=0;--e)if(4194303&this._data[3*e+0]||50331648&this._data[3*e+2])return e+(this._data[3*e+0]>>22);return 0}copyCellsFrom(e,t,i,s,r){const n=e._data;if(r)for(let r=s-1;r>=0;r--){for(let e=0;e<3;e++)this._data[3*(i+r)+e]=n[3*(t+r)+e];268435456&n[3*(t+r)+2]&&(this._extendedAttrs[i+r]=e._extendedAttrs[t+r])}else for(let r=0;r=t&&(this._combined[r-t+i]=e._combined[r])}}translateToString(e,t,i,s){t=t??0,i=i??this.length,e&&(i=Math.min(i,this.getTrimmedLength())),s&&(s.length=0);let r="";for(;t>22||1}return s&&s.push(t),r}}t.BufferLine=h},4841:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.getRangeLength=void 0,t.getRangeLength=function(e,t){if(e.start.y>e.end.y)throw new Error(`Buffer range end (${e.end.x}, ${e.end.y}) cannot be before start (${e.start.x}, ${e.start.y})`);return t*(e.end.y-e.start.y)+(e.end.x-e.start.x+1)}},4634:(e,t)=>{function i(e,t,i){if(t===e.length-1)return e[t].getTrimmedLength();const s=!e[t].hasContent(i-1)&&1===e[t].getWidth(i-1),r=2===e[t+1].getWidth(0);return s&&r?i-1:i}Object.defineProperty(t,"__esModule",{value:!0}),t.getWrappedLineTrimmedLength=t.reflowSmallerGetNewLineLengths=t.reflowLargerApplyNewLayout=t.reflowLargerCreateNewLayout=t.reflowLargerGetLinesToRemove=void 0,t.reflowLargerGetLinesToRemove=function(e,t,s,r,n){const o=[];for(let a=0;a=a&&r0&&(e>d||0===l[e].getTrimmedLength());e--)v++;v>0&&(o.push(a+l.length-v),o.push(v)),a+=l.length-1}return o},t.reflowLargerCreateNewLayout=function(e,t){const i=[];let s=0,r=t[s],n=0;for(let o=0;oi(e,r,t))).reduce(((e,t)=>e+t));let o=0,a=0,h=0;for(;hc&&(o-=c,a++);const l=2===e[a].getWidth(o-1);l&&o--;const d=l?s-1:s;r.push(d),h+=d}return r},t.getWrappedLineTrimmedLength=i},5295:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferSet=void 0;const s=i(8460),r=i(844),n=i(9092);class o extends r.Disposable{constructor(e,t){super(),this._optionsService=e,this._bufferService=t,this._onBufferActivate=this.register(new s.EventEmitter),this.onBufferActivate=this._onBufferActivate.event,this.reset(),this.register(this._optionsService.onSpecificOptionChange("scrollback",(()=>this.resize(this._bufferService.cols,this._bufferService.rows)))),this.register(this._optionsService.onSpecificOptionChange("tabStopWidth",(()=>this.setupTabStops())))}reset(){this._normal=new n.Buffer(!0,this._optionsService,this._bufferService),this._normal.fillViewportRows(),this._alt=new n.Buffer(!1,this._optionsService,this._bufferService),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}),this.setupTabStops()}get alt(){return this._alt}get active(){return this._activeBuffer}get normal(){return this._normal}activateNormalBuffer(){this._activeBuffer!==this._normal&&(this._normal.x=this._alt.x,this._normal.y=this._alt.y,this._alt.clearAllMarkers(),this._alt.clear(),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}))}activateAltBuffer(e){this._activeBuffer!==this._alt&&(this._alt.fillViewportRows(e),this._alt.x=this._normal.x,this._alt.y=this._normal.y,this._activeBuffer=this._alt,this._onBufferActivate.fire({activeBuffer:this._alt,inactiveBuffer:this._normal}))}resize(e,t){this._normal.resize(e,t),this._alt.resize(e,t),this.setupTabStops(e)}setupTabStops(e){this._normal.setupTabStops(e),this._alt.setupTabStops(e)}}t.BufferSet=o},511:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CellData=void 0;const s=i(482),r=i(643),n=i(3734);class o extends n.AttributeData{constructor(){super(...arguments),this.content=0,this.fg=0,this.bg=0,this.extended=new n.ExtendedAttrs,this.combinedData=""}static fromCharData(e){const t=new o;return t.setFromCharData(e),t}isCombined(){return 2097152&this.content}getWidth(){return this.content>>22}getChars(){return 2097152&this.content?this.combinedData:2097151&this.content?(0,s.stringFromCodePoint)(2097151&this.content):""}getCode(){return this.isCombined()?this.combinedData.charCodeAt(this.combinedData.length-1):2097151&this.content}setFromCharData(e){this.fg=e[r.CHAR_DATA_ATTR_INDEX],this.bg=0;let t=!1;if(e[r.CHAR_DATA_CHAR_INDEX].length>2)t=!0;else if(2===e[r.CHAR_DATA_CHAR_INDEX].length){const i=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(0);if(55296<=i&&i<=56319){const s=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(1);56320<=s&&s<=57343?this.content=1024*(i-55296)+s-56320+65536|e[r.CHAR_DATA_WIDTH_INDEX]<<22:t=!0}else t=!0}else this.content=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|e[r.CHAR_DATA_WIDTH_INDEX]<<22;t&&(this.combinedData=e[r.CHAR_DATA_CHAR_INDEX],this.content=2097152|e[r.CHAR_DATA_WIDTH_INDEX]<<22)}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}}t.CellData=o},643:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.WHITESPACE_CELL_CODE=t.WHITESPACE_CELL_WIDTH=t.WHITESPACE_CELL_CHAR=t.NULL_CELL_CODE=t.NULL_CELL_WIDTH=t.NULL_CELL_CHAR=t.CHAR_DATA_CODE_INDEX=t.CHAR_DATA_WIDTH_INDEX=t.CHAR_DATA_CHAR_INDEX=t.CHAR_DATA_ATTR_INDEX=t.DEFAULT_EXT=t.DEFAULT_ATTR=t.DEFAULT_COLOR=void 0,t.DEFAULT_COLOR=0,t.DEFAULT_ATTR=256|t.DEFAULT_COLOR<<9,t.DEFAULT_EXT=0,t.CHAR_DATA_ATTR_INDEX=0,t.CHAR_DATA_CHAR_INDEX=1,t.CHAR_DATA_WIDTH_INDEX=2,t.CHAR_DATA_CODE_INDEX=3,t.NULL_CELL_CHAR="",t.NULL_CELL_WIDTH=1,t.NULL_CELL_CODE=0,t.WHITESPACE_CELL_CHAR=" ",t.WHITESPACE_CELL_WIDTH=1,t.WHITESPACE_CELL_CODE=32},4863:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Marker=void 0;const s=i(8460),r=i(844);class n{get id(){return this._id}constructor(e){this.line=e,this.isDisposed=!1,this._disposables=[],this._id=n._nextId++,this._onDispose=this.register(new s.EventEmitter),this.onDispose=this._onDispose.event}dispose(){this.isDisposed||(this.isDisposed=!0,this.line=-1,this._onDispose.fire(),(0,r.disposeArray)(this._disposables),this._disposables.length=0)}register(e){return this._disposables.push(e),e}}t.Marker=n,n._nextId=1},7116:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DEFAULT_CHARSET=t.CHARSETS=void 0,t.CHARSETS={},t.DEFAULT_CHARSET=t.CHARSETS.B,t.CHARSETS[0]={"`":"◆",a:"▒",b:"␉",c:"␌",d:"␍",e:"␊",f:"°",g:"±",h:"␤",i:"␋",j:"┘",k:"┐",l:"┌",m:"└",n:"┼",o:"⎺",p:"⎻",q:"─",r:"⎼",s:"⎽",t:"├",u:"┤",v:"┴",w:"┬",x:"│",y:"≤",z:"≥","{":"π","|":"≠","}":"£","~":"·"},t.CHARSETS.A={"#":"£"},t.CHARSETS.B=void 0,t.CHARSETS[4]={"#":"£","@":"¾","[":"ij","\\":"½","]":"|","{":"¨","|":"f","}":"¼","~":"´"},t.CHARSETS.C=t.CHARSETS[5]={"[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS.R={"#":"£","@":"à","[":"°","\\":"ç","]":"§","{":"é","|":"ù","}":"è","~":"¨"},t.CHARSETS.Q={"@":"à","[":"â","\\":"ç","]":"ê","^":"î","`":"ô","{":"é","|":"ù","}":"è","~":"û"},t.CHARSETS.K={"@":"§","[":"Ä","\\":"Ö","]":"Ü","{":"ä","|":"ö","}":"ü","~":"ß"},t.CHARSETS.Y={"#":"£","@":"§","[":"°","\\":"ç","]":"é","`":"ù","{":"à","|":"ò","}":"è","~":"ì"},t.CHARSETS.E=t.CHARSETS[6]={"@":"Ä","[":"Æ","\\":"Ø","]":"Å","^":"Ü","`":"ä","{":"æ","|":"ø","}":"å","~":"ü"},t.CHARSETS.Z={"#":"£","@":"§","[":"¡","\\":"Ñ","]":"¿","{":"°","|":"ñ","}":"ç"},t.CHARSETS.H=t.CHARSETS[7]={"@":"É","[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS["="]={"#":"ù","@":"à","[":"é","\\":"ç","]":"ê","^":"î",_:"è","`":"ô","{":"ä","|":"ö","}":"ü","~":"û"}},2584:(e,t)=>{var i,s,r;Object.defineProperty(t,"__esModule",{value:!0}),t.C1_ESCAPED=t.C1=t.C0=void 0,function(e){e.NUL="\0",e.SOH="",e.STX="",e.ETX="",e.EOT="",e.ENQ="",e.ACK="",e.BEL="",e.BS="\b",e.HT="\t",e.LF="\n",e.VT="\v",e.FF="\f",e.CR="\r",e.SO="",e.SI="",e.DLE="",e.DC1="",e.DC2="",e.DC3="",e.DC4="",e.NAK="",e.SYN="",e.ETB="",e.CAN="",e.EM="",e.SUB="",e.ESC="",e.FS="",e.GS="",e.RS="",e.US="",e.SP=" ",e.DEL=""}(i||(t.C0=i={})),function(e){e.PAD="€",e.HOP="",e.BPH="‚",e.NBH="ƒ",e.IND="„",e.NEL="…",e.SSA="†",e.ESA="‡",e.HTS="ˆ",e.HTJ="‰",e.VTS="Š",e.PLD="‹",e.PLU="Œ",e.RI="",e.SS2="Ž",e.SS3="",e.DCS="",e.PU1="‘",e.PU2="’",e.STS="“",e.CCH="”",e.MW="•",e.SPA="–",e.EPA="—",e.SOS="˜",e.SGCI="™",e.SCI="š",e.CSI="›",e.ST="œ",e.OSC="",e.PM="ž",e.APC="Ÿ"}(s||(t.C1=s={})),function(e){e.ST=`${i.ESC}\\`}(r||(t.C1_ESCAPED=r={}))},7399:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.evaluateKeyboardEvent=void 0;const s=i(2584),r={48:["0",")"],49:["1","!"],50:["2","@"],51:["3","#"],52:["4","$"],53:["5","%"],54:["6","^"],55:["7","&"],56:["8","*"],57:["9","("],186:[";",":"],187:["=","+"],188:[",","<"],189:["-","_"],190:[".",">"],191:["/","?"],192:["`","~"],219:["[","{"],220:["\\","|"],221:["]","}"],222:["'",'"']};t.evaluateKeyboardEvent=function(e,t,i,n){const o={type:0,cancel:!1,key:void 0},a=(e.shiftKey?1:0)|(e.altKey?2:0)|(e.ctrlKey?4:0)|(e.metaKey?8:0);switch(e.keyCode){case 0:"UIKeyInputUpArrow"===e.key?o.key=t?s.C0.ESC+"OA":s.C0.ESC+"[A":"UIKeyInputLeftArrow"===e.key?o.key=t?s.C0.ESC+"OD":s.C0.ESC+"[D":"UIKeyInputRightArrow"===e.key?o.key=t?s.C0.ESC+"OC":s.C0.ESC+"[C":"UIKeyInputDownArrow"===e.key&&(o.key=t?s.C0.ESC+"OB":s.C0.ESC+"[B");break;case 8:o.key=e.ctrlKey?"\b":s.C0.DEL,e.altKey&&(o.key=s.C0.ESC+o.key);break;case 9:if(e.shiftKey){o.key=s.C0.ESC+"[Z";break}o.key=s.C0.HT,o.cancel=!0;break;case 13:o.key=e.altKey?s.C0.ESC+s.C0.CR:s.C0.CR,o.cancel=!0;break;case 27:o.key=s.C0.ESC,e.altKey&&(o.key=s.C0.ESC+s.C0.ESC),o.cancel=!0;break;case 37:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"D",o.key===s.C0.ESC+"[1;3D"&&(o.key=s.C0.ESC+(i?"b":"[1;5D"))):o.key=t?s.C0.ESC+"OD":s.C0.ESC+"[D";break;case 39:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"C",o.key===s.C0.ESC+"[1;3C"&&(o.key=s.C0.ESC+(i?"f":"[1;5C"))):o.key=t?s.C0.ESC+"OC":s.C0.ESC+"[C";break;case 38:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"A",i||o.key!==s.C0.ESC+"[1;3A"||(o.key=s.C0.ESC+"[1;5A")):o.key=t?s.C0.ESC+"OA":s.C0.ESC+"[A";break;case 40:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"B",i||o.key!==s.C0.ESC+"[1;3B"||(o.key=s.C0.ESC+"[1;5B")):o.key=t?s.C0.ESC+"OB":s.C0.ESC+"[B";break;case 45:e.shiftKey||e.ctrlKey||(o.key=s.C0.ESC+"[2~");break;case 46:o.key=a?s.C0.ESC+"[3;"+(a+1)+"~":s.C0.ESC+"[3~";break;case 36:o.key=a?s.C0.ESC+"[1;"+(a+1)+"H":t?s.C0.ESC+"OH":s.C0.ESC+"[H";break;case 35:o.key=a?s.C0.ESC+"[1;"+(a+1)+"F":t?s.C0.ESC+"OF":s.C0.ESC+"[F";break;case 33:e.shiftKey?o.type=2:e.ctrlKey?o.key=s.C0.ESC+"[5;"+(a+1)+"~":o.key=s.C0.ESC+"[5~";break;case 34:e.shiftKey?o.type=3:e.ctrlKey?o.key=s.C0.ESC+"[6;"+(a+1)+"~":o.key=s.C0.ESC+"[6~";break;case 112:o.key=a?s.C0.ESC+"[1;"+(a+1)+"P":s.C0.ESC+"OP";break;case 113:o.key=a?s.C0.ESC+"[1;"+(a+1)+"Q":s.C0.ESC+"OQ";break;case 114:o.key=a?s.C0.ESC+"[1;"+(a+1)+"R":s.C0.ESC+"OR";break;case 115:o.key=a?s.C0.ESC+"[1;"+(a+1)+"S":s.C0.ESC+"OS";break;case 116:o.key=a?s.C0.ESC+"[15;"+(a+1)+"~":s.C0.ESC+"[15~";break;case 117:o.key=a?s.C0.ESC+"[17;"+(a+1)+"~":s.C0.ESC+"[17~";break;case 118:o.key=a?s.C0.ESC+"[18;"+(a+1)+"~":s.C0.ESC+"[18~";break;case 119:o.key=a?s.C0.ESC+"[19;"+(a+1)+"~":s.C0.ESC+"[19~";break;case 120:o.key=a?s.C0.ESC+"[20;"+(a+1)+"~":s.C0.ESC+"[20~";break;case 121:o.key=a?s.C0.ESC+"[21;"+(a+1)+"~":s.C0.ESC+"[21~";break;case 122:o.key=a?s.C0.ESC+"[23;"+(a+1)+"~":s.C0.ESC+"[23~";break;case 123:o.key=a?s.C0.ESC+"[24;"+(a+1)+"~":s.C0.ESC+"[24~";break;default:if(!e.ctrlKey||e.shiftKey||e.altKey||e.metaKey)if(i&&!n||!e.altKey||e.metaKey)!i||e.altKey||e.ctrlKey||e.shiftKey||!e.metaKey?e.key&&!e.ctrlKey&&!e.altKey&&!e.metaKey&&e.keyCode>=48&&1===e.key.length?o.key=e.key:e.key&&e.ctrlKey&&("_"===e.key&&(o.key=s.C0.US),"@"===e.key&&(o.key=s.C0.NUL)):65===e.keyCode&&(o.type=1);else{const t=r[e.keyCode],i=t?.[e.shiftKey?1:0];if(i)o.key=s.C0.ESC+i;else if(e.keyCode>=65&&e.keyCode<=90){const t=e.ctrlKey?e.keyCode-64:e.keyCode+32;let i=String.fromCharCode(t);e.shiftKey&&(i=i.toUpperCase()),o.key=s.C0.ESC+i}else if(32===e.keyCode)o.key=s.C0.ESC+(e.ctrlKey?s.C0.NUL:" ");else if("Dead"===e.key&&e.code.startsWith("Key")){let t=e.code.slice(3,4);e.shiftKey||(t=t.toLowerCase()),o.key=s.C0.ESC+t,o.cancel=!0}}else e.keyCode>=65&&e.keyCode<=90?o.key=String.fromCharCode(e.keyCode-64):32===e.keyCode?o.key=s.C0.NUL:e.keyCode>=51&&e.keyCode<=55?o.key=String.fromCharCode(e.keyCode-51+27):56===e.keyCode?o.key=s.C0.DEL:219===e.keyCode?o.key=s.C0.ESC:220===e.keyCode?o.key=s.C0.FS:221===e.keyCode&&(o.key=s.C0.GS)}return o}},482:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Utf8ToUtf32=t.StringToUtf32=t.utf32ToString=t.stringFromCodePoint=void 0,t.stringFromCodePoint=function(e){return e>65535?(e-=65536,String.fromCharCode(55296+(e>>10))+String.fromCharCode(e%1024+56320)):String.fromCharCode(e)},t.utf32ToString=function(e,t=0,i=e.length){let s="";for(let r=t;r65535?(t-=65536,s+=String.fromCharCode(55296+(t>>10))+String.fromCharCode(t%1024+56320)):s+=String.fromCharCode(t)}return s},t.StringToUtf32=class{constructor(){this._interim=0}clear(){this._interim=0}decode(e,t){const i=e.length;if(!i)return 0;let s=0,r=0;if(this._interim){const i=e.charCodeAt(r++);56320<=i&&i<=57343?t[s++]=1024*(this._interim-55296)+i-56320+65536:(t[s++]=this._interim,t[s++]=i),this._interim=0}for(let n=r;n=i)return this._interim=r,s;const o=e.charCodeAt(n);56320<=o&&o<=57343?t[s++]=1024*(r-55296)+o-56320+65536:(t[s++]=r,t[s++]=o)}else 65279!==r&&(t[s++]=r)}return s}},t.Utf8ToUtf32=class{constructor(){this.interim=new Uint8Array(3)}clear(){this.interim.fill(0)}decode(e,t){const i=e.length;if(!i)return 0;let s,r,n,o,a=0,h=0,c=0;if(this.interim[0]){let s=!1,r=this.interim[0];r&=192==(224&r)?31:224==(240&r)?15:7;let n,o=0;for(;(n=63&this.interim[++o])&&o<4;)r<<=6,r|=n;const h=192==(224&this.interim[0])?2:224==(240&this.interim[0])?3:4,l=h-o;for(;c=i)return 0;if(n=e[c++],128!=(192&n)){c--,s=!0;break}this.interim[o++]=n,r<<=6,r|=63&n}s||(2===h?r<128?c--:t[a++]=r:3===h?r<2048||r>=55296&&r<=57343||65279===r||(t[a++]=r):r<65536||r>1114111||(t[a++]=r)),this.interim.fill(0)}const l=i-4;let d=c;for(;d=i)return this.interim[0]=s,a;if(r=e[d++],128!=(192&r)){d--;continue}if(h=(31&s)<<6|63&r,h<128){d--;continue}t[a++]=h}else if(224==(240&s)){if(d>=i)return this.interim[0]=s,a;if(r=e[d++],128!=(192&r)){d--;continue}if(d>=i)return this.interim[0]=s,this.interim[1]=r,a;if(n=e[d++],128!=(192&n)){d--;continue}if(h=(15&s)<<12|(63&r)<<6|63&n,h<2048||h>=55296&&h<=57343||65279===h)continue;t[a++]=h}else if(240==(248&s)){if(d>=i)return this.interim[0]=s,a;if(r=e[d++],128!=(192&r)){d--;continue}if(d>=i)return this.interim[0]=s,this.interim[1]=r,a;if(n=e[d++],128!=(192&n)){d--;continue}if(d>=i)return this.interim[0]=s,this.interim[1]=r,this.interim[2]=n,a;if(o=e[d++],128!=(192&o)){d--;continue}if(h=(7&s)<<18|(63&r)<<12|(63&n)<<6|63&o,h<65536||h>1114111)continue;t[a++]=h}}return a}}},225:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV6=void 0;const s=i(1480),r=[[768,879],[1155,1158],[1160,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1539],[1552,1557],[1611,1630],[1648,1648],[1750,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2305,2306],[2364,2364],[2369,2376],[2381,2381],[2385,2388],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2672,2673],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2817,2817],[2876,2876],[2879,2879],[2881,2883],[2893,2893],[2902,2902],[2946,2946],[3008,3008],[3021,3021],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3393,3395],[3405,3405],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3769],[3771,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3984,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4146],[4150,4151],[4153,4153],[4184,4185],[4448,4607],[4959,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6157],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7616,7626],[7678,7679],[8203,8207],[8234,8238],[8288,8291],[8298,8303],[8400,8431],[12330,12335],[12441,12442],[43014,43014],[43019,43019],[43045,43046],[64286,64286],[65024,65039],[65056,65059],[65279,65279],[65529,65531]],n=[[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[917505,917505],[917536,917631],[917760,917999]];let o;t.UnicodeV6=class{constructor(){if(this.version="6",!o){o=new Uint8Array(65536),o.fill(1),o[0]=0,o.fill(0,1,32),o.fill(0,127,160),o.fill(2,4352,4448),o[9001]=2,o[9002]=2,o.fill(2,11904,42192),o[12351]=1,o.fill(2,44032,55204),o.fill(2,63744,64256),o.fill(2,65040,65050),o.fill(2,65072,65136),o.fill(2,65280,65377),o.fill(2,65504,65511);for(let e=0;et[r][1])return!1;for(;r>=s;)if(i=s+r>>1,e>t[i][1])s=i+1;else{if(!(e=131072&&e<=196605||e>=196608&&e<=262141?2:1}charProperties(e,t){let i=this.wcwidth(e),r=0===i&&0!==t;if(r){const e=s.UnicodeService.extractWidth(t);0===e?r=!1:e>i&&(i=e)}return s.UnicodeService.createPropertyValue(0,i,r)}}},5981:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.WriteBuffer=void 0;const s=i(8460),r=i(844);class n extends r.Disposable{constructor(e){super(),this._action=e,this._writeBuffer=[],this._callbacks=[],this._pendingData=0,this._bufferOffset=0,this._isSyncWriting=!1,this._syncCalls=0,this._didUserInput=!1,this._onWriteParsed=this.register(new s.EventEmitter),this.onWriteParsed=this._onWriteParsed.event}handleUserInput(){this._didUserInput=!0}writeSync(e,t){if(void 0!==t&&this._syncCalls>t)return void(this._syncCalls=0);if(this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(void 0),this._syncCalls++,this._isSyncWriting)return;let i;for(this._isSyncWriting=!0;i=this._writeBuffer.shift();){this._action(i);const e=this._callbacks.shift();e&&e()}this._pendingData=0,this._bufferOffset=2147483647,this._isSyncWriting=!1,this._syncCalls=0}write(e,t){if(this._pendingData>5e7)throw new Error("write data discarded, use flow control to avoid losing data");if(!this._writeBuffer.length){if(this._bufferOffset=0,this._didUserInput)return this._didUserInput=!1,this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t),void this._innerWrite();setTimeout((()=>this._innerWrite()))}this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t)}_innerWrite(e=0,t=!0){const i=e||Date.now();for(;this._writeBuffer.length>this._bufferOffset;){const e=this._writeBuffer[this._bufferOffset],s=this._action(e,t);if(s){const e=e=>Date.now()-i>=12?setTimeout((()=>this._innerWrite(0,e))):this._innerWrite(i,e);return void s.catch((e=>(queueMicrotask((()=>{throw e})),Promise.resolve(!1)))).then(e)}const r=this._callbacks[this._bufferOffset];if(r&&r(),this._bufferOffset++,this._pendingData-=e.length,Date.now()-i>=12)break}this._writeBuffer.length>this._bufferOffset?(this._bufferOffset>50&&(this._writeBuffer=this._writeBuffer.slice(this._bufferOffset),this._callbacks=this._callbacks.slice(this._bufferOffset),this._bufferOffset=0),setTimeout((()=>this._innerWrite()))):(this._writeBuffer.length=0,this._callbacks.length=0,this._pendingData=0,this._bufferOffset=0),this._onWriteParsed.fire()}}t.WriteBuffer=n},5941:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.toRgbString=t.parseColor=void 0;const i=/^([\da-f])\/([\da-f])\/([\da-f])$|^([\da-f]{2})\/([\da-f]{2})\/([\da-f]{2})$|^([\da-f]{3})\/([\da-f]{3})\/([\da-f]{3})$|^([\da-f]{4})\/([\da-f]{4})\/([\da-f]{4})$/,s=/^[\da-f]+$/;function r(e,t){const i=e.toString(16),s=i.length<2?"0"+i:i;switch(t){case 4:return i[0];case 8:return s;case 12:return(s+s).slice(0,3);default:return s+s}}t.parseColor=function(e){if(!e)return;let t=e.toLowerCase();if(0===t.indexOf("rgb:")){t=t.slice(4);const e=i.exec(t);if(e){const t=e[1]?15:e[4]?255:e[7]?4095:65535;return[Math.round(parseInt(e[1]||e[4]||e[7]||e[10],16)/t*255),Math.round(parseInt(e[2]||e[5]||e[8]||e[11],16)/t*255),Math.round(parseInt(e[3]||e[6]||e[9]||e[12],16)/t*255)]}}else if(0===t.indexOf("#")&&(t=t.slice(1),s.exec(t)&&[3,6,9,12].includes(t.length))){const e=t.length/3,i=[0,0,0];for(let s=0;s<3;++s){const r=parseInt(t.slice(e*s,e*s+e),16);i[s]=1===e?r<<4:2===e?r:3===e?r>>4:r>>8}return i}},t.toRgbString=function(e,t=16){const[i,s,n]=e;return`rgb:${r(i,t)}/${r(s,t)}/${r(n,t)}`}},5770:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.PAYLOAD_LIMIT=void 0,t.PAYLOAD_LIMIT=1e7},6351:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DcsHandler=t.DcsParser=void 0;const s=i(482),r=i(8742),n=i(5770),o=[];t.DcsParser=class{constructor(){this._handlers=Object.create(null),this._active=o,this._ident=0,this._handlerFb=()=>{},this._stack={paused:!1,loopPosition:0,fallThrough:!1}}dispose(){this._handlers=Object.create(null),this._handlerFb=()=>{},this._active=o}registerHandler(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);const i=this._handlers[e];return i.push(t),{dispose:()=>{const e=i.indexOf(t);-1!==e&&i.splice(e,1)}}}clearHandler(e){this._handlers[e]&&delete this._handlers[e]}setHandlerFallback(e){this._handlerFb=e}reset(){if(this._active.length)for(let e=this._stack.paused?this._stack.loopPosition-1:this._active.length-1;e>=0;--e)this._active[e].unhook(!1);this._stack.paused=!1,this._active=o,this._ident=0}hook(e,t){if(this.reset(),this._ident=e,this._active=this._handlers[e]||o,this._active.length)for(let e=this._active.length-1;e>=0;e--)this._active[e].hook(t);else this._handlerFb(this._ident,"HOOK",t)}put(e,t,i){if(this._active.length)for(let s=this._active.length-1;s>=0;s--)this._active[s].put(e,t,i);else this._handlerFb(this._ident,"PUT",(0,s.utf32ToString)(e,t,i))}unhook(e,t=!0){if(this._active.length){let i=!1,s=this._active.length-1,r=!1;if(this._stack.paused&&(s=this._stack.loopPosition-1,i=t,r=this._stack.fallThrough,this._stack.paused=!1),!r&&!1===i){for(;s>=0&&(i=this._active[s].unhook(e),!0!==i);s--)if(i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!1,i;s--}for(;s>=0;s--)if(i=this._active[s].unhook(!1),i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!0,i}else this._handlerFb(this._ident,"UNHOOK",e);this._active=o,this._ident=0}};const a=new r.Params;a.addParam(0),t.DcsHandler=class{constructor(e){this._handler=e,this._data="",this._params=a,this._hitLimit=!1}hook(e){this._params=e.length>1||e.params[0]?e.clone():a,this._data="",this._hitLimit=!1}put(e,t,i){this._hitLimit||(this._data+=(0,s.utf32ToString)(e,t,i),this._data.length>n.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))}unhook(e){let t=!1;if(this._hitLimit)t=!1;else if(e&&(t=this._handler(this._data,this._params),t instanceof Promise))return t.then((e=>(this._params=a,this._data="",this._hitLimit=!1,e)));return this._params=a,this._data="",this._hitLimit=!1,t}}},2015:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.EscapeSequenceParser=t.VT500_TRANSITION_TABLE=t.TransitionTable=void 0;const s=i(844),r=i(8742),n=i(6242),o=i(6351);class a{constructor(e){this.table=new Uint8Array(e)}setDefault(e,t){this.table.fill(e<<4|t)}add(e,t,i,s){this.table[t<<8|e]=i<<4|s}addMany(e,t,i,s){for(let r=0;rt)),i=(e,i)=>t.slice(e,i),s=i(32,127),r=i(0,24);r.push(25),r.push.apply(r,i(28,32));const n=i(0,14);let o;for(o in e.setDefault(1,0),e.addMany(s,0,2,0),n)e.addMany([24,26,153,154],o,3,0),e.addMany(i(128,144),o,3,0),e.addMany(i(144,152),o,3,0),e.add(156,o,0,0),e.add(27,o,11,1),e.add(157,o,4,8),e.addMany([152,158,159],o,0,7),e.add(155,o,11,3),e.add(144,o,11,9);return e.addMany(r,0,3,0),e.addMany(r,1,3,1),e.add(127,1,0,1),e.addMany(r,8,0,8),e.addMany(r,3,3,3),e.add(127,3,0,3),e.addMany(r,4,3,4),e.add(127,4,0,4),e.addMany(r,6,3,6),e.addMany(r,5,3,5),e.add(127,5,0,5),e.addMany(r,2,3,2),e.add(127,2,0,2),e.add(93,1,4,8),e.addMany(s,8,5,8),e.add(127,8,5,8),e.addMany([156,27,24,26,7],8,6,0),e.addMany(i(28,32),8,0,8),e.addMany([88,94,95],1,0,7),e.addMany(s,7,0,7),e.addMany(r,7,0,7),e.add(156,7,0,0),e.add(127,7,0,7),e.add(91,1,11,3),e.addMany(i(64,127),3,7,0),e.addMany(i(48,60),3,8,4),e.addMany([60,61,62,63],3,9,4),e.addMany(i(48,60),4,8,4),e.addMany(i(64,127),4,7,0),e.addMany([60,61,62,63],4,0,6),e.addMany(i(32,64),6,0,6),e.add(127,6,0,6),e.addMany(i(64,127),6,0,0),e.addMany(i(32,48),3,9,5),e.addMany(i(32,48),5,9,5),e.addMany(i(48,64),5,0,6),e.addMany(i(64,127),5,7,0),e.addMany(i(32,48),4,9,5),e.addMany(i(32,48),1,9,2),e.addMany(i(32,48),2,9,2),e.addMany(i(48,127),2,10,0),e.addMany(i(48,80),1,10,0),e.addMany(i(81,88),1,10,0),e.addMany([89,90,92],1,10,0),e.addMany(i(96,127),1,10,0),e.add(80,1,11,9),e.addMany(r,9,0,9),e.add(127,9,0,9),e.addMany(i(28,32),9,0,9),e.addMany(i(32,48),9,9,12),e.addMany(i(48,60),9,8,10),e.addMany([60,61,62,63],9,9,10),e.addMany(r,11,0,11),e.addMany(i(32,128),11,0,11),e.addMany(i(28,32),11,0,11),e.addMany(r,10,0,10),e.add(127,10,0,10),e.addMany(i(28,32),10,0,10),e.addMany(i(48,60),10,8,10),e.addMany([60,61,62,63],10,0,11),e.addMany(i(32,48),10,9,12),e.addMany(r,12,0,12),e.add(127,12,0,12),e.addMany(i(28,32),12,0,12),e.addMany(i(32,48),12,9,12),e.addMany(i(48,64),12,0,11),e.addMany(i(64,127),12,12,13),e.addMany(i(64,127),10,12,13),e.addMany(i(64,127),9,12,13),e.addMany(r,13,13,13),e.addMany(s,13,13,13),e.add(127,13,0,13),e.addMany([27,156,24,26],13,14,0),e.add(h,0,2,0),e.add(h,8,5,8),e.add(h,6,0,6),e.add(h,11,0,11),e.add(h,13,13,13),e}();class c extends s.Disposable{constructor(e=t.VT500_TRANSITION_TABLE){super(),this._transitions=e,this._parseStack={state:0,handlers:[],handlerPos:0,transition:0,chunkPos:0},this.initialState=0,this.currentState=this.initialState,this._params=new r.Params,this._params.addParam(0),this._collect=0,this.precedingJoinState=0,this._printHandlerFb=(e,t,i)=>{},this._executeHandlerFb=e=>{},this._csiHandlerFb=(e,t)=>{},this._escHandlerFb=e=>{},this._errorHandlerFb=e=>e,this._printHandler=this._printHandlerFb,this._executeHandlers=Object.create(null),this._csiHandlers=Object.create(null),this._escHandlers=Object.create(null),this.register((0,s.toDisposable)((()=>{this._csiHandlers=Object.create(null),this._executeHandlers=Object.create(null),this._escHandlers=Object.create(null)}))),this._oscParser=this.register(new n.OscParser),this._dcsParser=this.register(new o.DcsParser),this._errorHandler=this._errorHandlerFb,this.registerEscHandler({final:"\\"},(()=>!0))}_identifier(e,t=[64,126]){let i=0;if(e.prefix){if(e.prefix.length>1)throw new Error("only one byte as prefix supported");if(i=e.prefix.charCodeAt(0),i&&60>i||i>63)throw new Error("prefix must be in range 0x3c .. 0x3f")}if(e.intermediates){if(e.intermediates.length>2)throw new Error("only two bytes as intermediates are supported");for(let t=0;ts||s>47)throw new Error("intermediate must be in range 0x20 .. 0x2f");i<<=8,i|=s}}if(1!==e.final.length)throw new Error("final must be a single byte");const s=e.final.charCodeAt(0);if(t[0]>s||s>t[1])throw new Error(`final must be in range ${t[0]} .. ${t[1]}`);return i<<=8,i|=s,i}identToString(e){const t=[];for(;e;)t.push(String.fromCharCode(255&e)),e>>=8;return t.reverse().join("")}setPrintHandler(e){this._printHandler=e}clearPrintHandler(){this._printHandler=this._printHandlerFb}registerEscHandler(e,t){const i=this._identifier(e,[48,126]);void 0===this._escHandlers[i]&&(this._escHandlers[i]=[]);const s=this._escHandlers[i];return s.push(t),{dispose:()=>{const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}}clearEscHandler(e){this._escHandlers[this._identifier(e,[48,126])]&&delete this._escHandlers[this._identifier(e,[48,126])]}setEscHandlerFallback(e){this._escHandlerFb=e}setExecuteHandler(e,t){this._executeHandlers[e.charCodeAt(0)]=t}clearExecuteHandler(e){this._executeHandlers[e.charCodeAt(0)]&&delete this._executeHandlers[e.charCodeAt(0)]}setExecuteHandlerFallback(e){this._executeHandlerFb=e}registerCsiHandler(e,t){const i=this._identifier(e);void 0===this._csiHandlers[i]&&(this._csiHandlers[i]=[]);const s=this._csiHandlers[i];return s.push(t),{dispose:()=>{const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}}clearCsiHandler(e){this._csiHandlers[this._identifier(e)]&&delete this._csiHandlers[this._identifier(e)]}setCsiHandlerFallback(e){this._csiHandlerFb=e}registerDcsHandler(e,t){return this._dcsParser.registerHandler(this._identifier(e),t)}clearDcsHandler(e){this._dcsParser.clearHandler(this._identifier(e))}setDcsHandlerFallback(e){this._dcsParser.setHandlerFallback(e)}registerOscHandler(e,t){return this._oscParser.registerHandler(e,t)}clearOscHandler(e){this._oscParser.clearHandler(e)}setOscHandlerFallback(e){this._oscParser.setHandlerFallback(e)}setErrorHandler(e){this._errorHandler=e}clearErrorHandler(){this._errorHandler=this._errorHandlerFb}reset(){this.currentState=this.initialState,this._oscParser.reset(),this._dcsParser.reset(),this._params.reset(),this._params.addParam(0),this._collect=0,this.precedingJoinState=0,0!==this._parseStack.state&&(this._parseStack.state=2,this._parseStack.handlers=[])}_preserveStack(e,t,i,s,r){this._parseStack.state=e,this._parseStack.handlers=t,this._parseStack.handlerPos=i,this._parseStack.transition=s,this._parseStack.chunkPos=r}parse(e,t,i){let s,r=0,n=0,o=0;if(this._parseStack.state)if(2===this._parseStack.state)this._parseStack.state=0,o=this._parseStack.chunkPos+1;else{if(void 0===i||1===this._parseStack.state)throw this._parseStack.state=1,new Error("improper continuation due to previous async handler, giving up parsing");const t=this._parseStack.handlers;let n=this._parseStack.handlerPos-1;switch(this._parseStack.state){case 3:if(!1===i&&n>-1)for(;n>=0&&(s=t[n](this._params),!0!==s);n--)if(s instanceof Promise)return this._parseStack.handlerPos=n,s;this._parseStack.handlers=[];break;case 4:if(!1===i&&n>-1)for(;n>=0&&(s=t[n](),!0!==s);n--)if(s instanceof Promise)return this._parseStack.handlerPos=n,s;this._parseStack.handlers=[];break;case 6:if(r=e[this._parseStack.chunkPos],s=this._dcsParser.unhook(24!==r&&26!==r,i),s)return s;27===r&&(this._parseStack.transition|=1),this._params.reset(),this._params.addParam(0),this._collect=0;break;case 5:if(r=e[this._parseStack.chunkPos],s=this._oscParser.end(24!==r&&26!==r,i),s)return s;27===r&&(this._parseStack.transition|=1),this._params.reset(),this._params.addParam(0),this._collect=0}this._parseStack.state=0,o=this._parseStack.chunkPos+1,this.precedingJoinState=0,this.currentState=15&this._parseStack.transition}for(let i=o;i>4){case 2:for(let s=i+1;;++s){if(s>=t||(r=e[s])<32||r>126&&r=t||(r=e[s])<32||r>126&&r=t||(r=e[s])<32||r>126&&r=t||(r=e[s])<32||r>126&&r=0&&(s=o[a](this._params),!0!==s);a--)if(s instanceof Promise)return this._preserveStack(3,o,a,n,i),s;a<0&&this._csiHandlerFb(this._collect<<8|r,this._params),this.precedingJoinState=0;break;case 8:do{switch(r){case 59:this._params.addParam(0);break;case 58:this._params.addSubParam(-1);break;default:this._params.addDigit(r-48)}}while(++i47&&r<60);i--;break;case 9:this._collect<<=8,this._collect|=r;break;case 10:const c=this._escHandlers[this._collect<<8|r];let l=c?c.length-1:-1;for(;l>=0&&(s=c[l](),!0!==s);l--)if(s instanceof Promise)return this._preserveStack(4,c,l,n,i),s;l<0&&this._escHandlerFb(this._collect<<8|r),this.precedingJoinState=0;break;case 11:this._params.reset(),this._params.addParam(0),this._collect=0;break;case 12:this._dcsParser.hook(this._collect<<8|r,this._params);break;case 13:for(let s=i+1;;++s)if(s>=t||24===(r=e[s])||26===r||27===r||r>127&&r=t||(r=e[s])<32||r>127&&r{Object.defineProperty(t,"__esModule",{value:!0}),t.OscHandler=t.OscParser=void 0;const s=i(5770),r=i(482),n=[];t.OscParser=class{constructor(){this._state=0,this._active=n,this._id=-1,this._handlers=Object.create(null),this._handlerFb=()=>{},this._stack={paused:!1,loopPosition:0,fallThrough:!1}}registerHandler(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);const i=this._handlers[e];return i.push(t),{dispose:()=>{const e=i.indexOf(t);-1!==e&&i.splice(e,1)}}}clearHandler(e){this._handlers[e]&&delete this._handlers[e]}setHandlerFallback(e){this._handlerFb=e}dispose(){this._handlers=Object.create(null),this._handlerFb=()=>{},this._active=n}reset(){if(2===this._state)for(let e=this._stack.paused?this._stack.loopPosition-1:this._active.length-1;e>=0;--e)this._active[e].end(!1);this._stack.paused=!1,this._active=n,this._id=-1,this._state=0}_start(){if(this._active=this._handlers[this._id]||n,this._active.length)for(let e=this._active.length-1;e>=0;e--)this._active[e].start();else this._handlerFb(this._id,"START")}_put(e,t,i){if(this._active.length)for(let s=this._active.length-1;s>=0;s--)this._active[s].put(e,t,i);else this._handlerFb(this._id,"PUT",(0,r.utf32ToString)(e,t,i))}start(){this.reset(),this._state=1}put(e,t,i){if(3!==this._state){if(1===this._state)for(;t0&&this._put(e,t,i)}}end(e,t=!0){if(0!==this._state){if(3!==this._state)if(1===this._state&&this._start(),this._active.length){let i=!1,s=this._active.length-1,r=!1;if(this._stack.paused&&(s=this._stack.loopPosition-1,i=t,r=this._stack.fallThrough,this._stack.paused=!1),!r&&!1===i){for(;s>=0&&(i=this._active[s].end(e),!0!==i);s--)if(i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!1,i;s--}for(;s>=0;s--)if(i=this._active[s].end(!1),i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!0,i}else this._handlerFb(this._id,"END",e);this._active=n,this._id=-1,this._state=0}}},t.OscHandler=class{constructor(e){this._handler=e,this._data="",this._hitLimit=!1}start(){this._data="",this._hitLimit=!1}put(e,t,i){this._hitLimit||(this._data+=(0,r.utf32ToString)(e,t,i),this._data.length>s.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))}end(e){let t=!1;if(this._hitLimit)t=!1;else if(e&&(t=this._handler(this._data),t instanceof Promise))return t.then((e=>(this._data="",this._hitLimit=!1,e)));return this._data="",this._hitLimit=!1,t}}},8742:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Params=void 0;const i=2147483647;class s{static fromArray(e){const t=new s;if(!e.length)return t;for(let i=Array.isArray(e[0])?1:0;i256)throw new Error("maxSubParamsLength must not be greater than 256");this.params=new Int32Array(e),this.length=0,this._subParams=new Int32Array(t),this._subParamsLength=0,this._subParamsIdx=new Uint16Array(e),this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}clone(){const e=new s(this.maxLength,this.maxSubParamsLength);return e.params.set(this.params),e.length=this.length,e._subParams.set(this._subParams),e._subParamsLength=this._subParamsLength,e._subParamsIdx.set(this._subParamsIdx),e._rejectDigits=this._rejectDigits,e._rejectSubDigits=this._rejectSubDigits,e._digitIsSub=this._digitIsSub,e}toArray(){const e=[];for(let t=0;t>8,s=255&this._subParamsIdx[t];s-i>0&&e.push(Array.prototype.slice.call(this._subParams,i,s))}return e}reset(){this.length=0,this._subParamsLength=0,this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}addParam(e){if(this._digitIsSub=!1,this.length>=this.maxLength)this._rejectDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParamsIdx[this.length]=this._subParamsLength<<8|this._subParamsLength,this.params[this.length++]=e>i?i:e}}addSubParam(e){if(this._digitIsSub=!0,this.length)if(this._rejectDigits||this._subParamsLength>=this.maxSubParamsLength)this._rejectSubDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParams[this._subParamsLength++]=e>i?i:e,this._subParamsIdx[this.length-1]++}}hasSubParams(e){return(255&this._subParamsIdx[e])-(this._subParamsIdx[e]>>8)>0}getSubParams(e){const t=this._subParamsIdx[e]>>8,i=255&this._subParamsIdx[e];return i-t>0?this._subParams.subarray(t,i):null}getSubParamsAll(){const e={};for(let t=0;t>8,s=255&this._subParamsIdx[t];s-i>0&&(e[t]=this._subParams.slice(i,s))}return e}addDigit(e){let t;if(this._rejectDigits||!(t=this._digitIsSub?this._subParamsLength:this.length)||this._digitIsSub&&this._rejectSubDigits)return;const s=this._digitIsSub?this._subParams:this.params,r=s[t-1];s[t-1]=~r?Math.min(10*r+e,i):e}}t.Params=s},5741:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.AddonManager=void 0,t.AddonManager=class{constructor(){this._addons=[]}dispose(){for(let e=this._addons.length-1;e>=0;e--)this._addons[e].instance.dispose()}loadAddon(e,t){const i={instance:t,dispose:t.dispose,isDisposed:!1};this._addons.push(i),t.dispose=()=>this._wrappedAddonDispose(i),t.activate(e)}_wrappedAddonDispose(e){if(e.isDisposed)return;let t=-1;for(let i=0;i{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferApiView=void 0;const s=i(3785),r=i(511);t.BufferApiView=class{constructor(e,t){this._buffer=e,this.type=t}init(e){return this._buffer=e,this}get cursorY(){return this._buffer.y}get cursorX(){return this._buffer.x}get viewportY(){return this._buffer.ydisp}get baseY(){return this._buffer.ybase}get length(){return this._buffer.lines.length}getLine(e){const t=this._buffer.lines.get(e);if(t)return new s.BufferLineApiView(t)}getNullCell(){return new r.CellData}}},3785:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferLineApiView=void 0;const s=i(511);t.BufferLineApiView=class{constructor(e){this._line=e}get isWrapped(){return this._line.isWrapped}get length(){return this._line.length}getCell(e,t){if(!(e<0||e>=this._line.length))return t?(this._line.loadCell(e,t),t):this._line.loadCell(e,new s.CellData)}translateToString(e,t,i){return this._line.translateToString(e,t,i)}}},8285:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferNamespaceApi=void 0;const s=i(8771),r=i(8460),n=i(844);class o extends n.Disposable{constructor(e){super(),this._core=e,this._onBufferChange=this.register(new r.EventEmitter),this.onBufferChange=this._onBufferChange.event,this._normal=new s.BufferApiView(this._core.buffers.normal,"normal"),this._alternate=new s.BufferApiView(this._core.buffers.alt,"alternate"),this._core.buffers.onBufferActivate((()=>this._onBufferChange.fire(this.active)))}get active(){if(this._core.buffers.active===this._core.buffers.normal)return this.normal;if(this._core.buffers.active===this._core.buffers.alt)return this.alternate;throw new Error("Active buffer is neither normal nor alternate")}get normal(){return this._normal.init(this._core.buffers.normal)}get alternate(){return this._alternate.init(this._core.buffers.alt)}}t.BufferNamespaceApi=o},7975:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ParserApi=void 0,t.ParserApi=class{constructor(e){this._core=e}registerCsiHandler(e,t){return this._core.registerCsiHandler(e,(e=>t(e.toArray())))}addCsiHandler(e,t){return this.registerCsiHandler(e,t)}registerDcsHandler(e,t){return this._core.registerDcsHandler(e,((e,i)=>t(e,i.toArray())))}addDcsHandler(e,t){return this.registerDcsHandler(e,t)}registerEscHandler(e,t){return this._core.registerEscHandler(e,t)}addEscHandler(e,t){return this.registerEscHandler(e,t)}registerOscHandler(e,t){return this._core.registerOscHandler(e,t)}addOscHandler(e,t){return this.registerOscHandler(e,t)}}},7090:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeApi=void 0,t.UnicodeApi=class{constructor(e){this._core=e}register(e){this._core.unicodeService.register(e)}get versions(){return this._core.unicodeService.versions}get activeVersion(){return this._core.unicodeService.activeVersion}set activeVersion(e){this._core.unicodeService.activeVersion=e}}},744:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.BufferService=t.MINIMUM_ROWS=t.MINIMUM_COLS=void 0;const n=i(8460),o=i(844),a=i(5295),h=i(2585);t.MINIMUM_COLS=2,t.MINIMUM_ROWS=1;let c=t.BufferService=class extends o.Disposable{get buffer(){return this.buffers.active}constructor(e){super(),this.isUserScrolling=!1,this._onResize=this.register(new n.EventEmitter),this.onResize=this._onResize.event,this._onScroll=this.register(new n.EventEmitter),this.onScroll=this._onScroll.event,this.cols=Math.max(e.rawOptions.cols||0,t.MINIMUM_COLS),this.rows=Math.max(e.rawOptions.rows||0,t.MINIMUM_ROWS),this.buffers=this.register(new a.BufferSet(e,this))}resize(e,t){this.cols=e,this.rows=t,this.buffers.resize(e,t),this._onResize.fire({cols:e,rows:t})}reset(){this.buffers.reset(),this.isUserScrolling=!1}scroll(e,t=!1){const i=this.buffer;let s;s=this._cachedBlankLine,s&&s.length===this.cols&&s.getFg(0)===e.fg&&s.getBg(0)===e.bg||(s=i.getBlankLine(e,t),this._cachedBlankLine=s),s.isWrapped=t;const r=i.ybase+i.scrollTop,n=i.ybase+i.scrollBottom;if(0===i.scrollTop){const e=i.lines.isFull;n===i.lines.length-1?e?i.lines.recycle().copyFrom(s):i.lines.push(s.clone()):i.lines.splice(n+1,0,s.clone()),e?this.isUserScrolling&&(i.ydisp=Math.max(i.ydisp-1,0)):(i.ybase++,this.isUserScrolling||i.ydisp++)}else{const e=n-r+1;i.lines.shiftElements(r+1,e-1,-1),i.lines.set(n,s.clone())}this.isUserScrolling||(i.ydisp=i.ybase),this._onScroll.fire(i.ydisp)}scrollLines(e,t,i){const s=this.buffer;if(e<0){if(0===s.ydisp)return;this.isUserScrolling=!0}else e+s.ydisp>=s.ybase&&(this.isUserScrolling=!1);const r=s.ydisp;s.ydisp=Math.max(Math.min(s.ydisp+e,s.ybase),0),r!==s.ydisp&&(t||this._onScroll.fire(s.ydisp))}};t.BufferService=c=s([r(0,h.IOptionsService)],c)},7994:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CharsetService=void 0,t.CharsetService=class{constructor(){this.glevel=0,this._charsets=[]}reset(){this.charset=void 0,this._charsets=[],this.glevel=0}setgLevel(e){this.glevel=e,this.charset=this._charsets[e]}setgCharset(e,t){this._charsets[e]=t,this.glevel===e&&(this.charset=t)}}},1753:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CoreMouseService=void 0;const n=i(2585),o=i(8460),a=i(844),h={NONE:{events:0,restrict:()=>!1},X10:{events:1,restrict:e=>4!==e.button&&1===e.action&&(e.ctrl=!1,e.alt=!1,e.shift=!1,!0)},VT200:{events:19,restrict:e=>32!==e.action},DRAG:{events:23,restrict:e=>32!==e.action||3!==e.button},ANY:{events:31,restrict:e=>!0}};function c(e,t){let i=(e.ctrl?16:0)|(e.shift?4:0)|(e.alt?8:0);return 4===e.button?(i|=64,i|=e.action):(i|=3&e.button,4&e.button&&(i|=64),8&e.button&&(i|=128),32===e.action?i|=32:0!==e.action||t||(i|=3)),i}const l=String.fromCharCode,d={DEFAULT:e=>{const t=[c(e,!1)+32,e.col+32,e.row+32];return t[0]>255||t[1]>255||t[2]>255?"":`${l(t[0])}${l(t[1])}${l(t[2])}`},SGR:e=>{const t=0===e.action&&4!==e.button?"m":"M";return`[<${c(e,!0)};${e.col};${e.row}${t}`},SGR_PIXELS:e=>{const t=0===e.action&&4!==e.button?"m":"M";return`[<${c(e,!0)};${e.x};${e.y}${t}`}};let _=t.CoreMouseService=class extends a.Disposable{constructor(e,t){super(),this._bufferService=e,this._coreService=t,this._protocols={},this._encodings={},this._activeProtocol="",this._activeEncoding="",this._lastEvent=null,this._onProtocolChange=this.register(new o.EventEmitter),this.onProtocolChange=this._onProtocolChange.event;for(const e of Object.keys(h))this.addProtocol(e,h[e]);for(const e of Object.keys(d))this.addEncoding(e,d[e]);this.reset()}addProtocol(e,t){this._protocols[e]=t}addEncoding(e,t){this._encodings[e]=t}get activeProtocol(){return this._activeProtocol}get areMouseEventsActive(){return 0!==this._protocols[this._activeProtocol].events}set activeProtocol(e){if(!this._protocols[e])throw new Error(`unknown protocol "${e}"`);this._activeProtocol=e,this._onProtocolChange.fire(this._protocols[e].events)}get activeEncoding(){return this._activeEncoding}set activeEncoding(e){if(!this._encodings[e])throw new Error(`unknown encoding "${e}"`);this._activeEncoding=e}reset(){this.activeProtocol="NONE",this.activeEncoding="DEFAULT",this._lastEvent=null}triggerMouseEvent(e){if(e.col<0||e.col>=this._bufferService.cols||e.row<0||e.row>=this._bufferService.rows)return!1;if(4===e.button&&32===e.action)return!1;if(3===e.button&&32!==e.action)return!1;if(4!==e.button&&(2===e.action||3===e.action))return!1;if(e.col++,e.row++,32===e.action&&this._lastEvent&&this._equalEvents(this._lastEvent,e,"SGR_PIXELS"===this._activeEncoding))return!1;if(!this._protocols[this._activeProtocol].restrict(e))return!1;const t=this._encodings[this._activeEncoding](e);return t&&("DEFAULT"===this._activeEncoding?this._coreService.triggerBinaryEvent(t):this._coreService.triggerDataEvent(t,!0)),this._lastEvent=e,!0}explainEvents(e){return{down:!!(1&e),up:!!(2&e),drag:!!(4&e),move:!!(8&e),wheel:!!(16&e)}}_equalEvents(e,t,i){if(i){if(e.x!==t.x)return!1;if(e.y!==t.y)return!1}else{if(e.col!==t.col)return!1;if(e.row!==t.row)return!1}return e.button===t.button&&e.action===t.action&&e.ctrl===t.ctrl&&e.alt===t.alt&&e.shift===t.shift}};t.CoreMouseService=_=s([r(0,n.IBufferService),r(1,n.ICoreService)],_)},6975:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CoreService=void 0;const n=i(1439),o=i(8460),a=i(844),h=i(2585),c=Object.freeze({insertMode:!1}),l=Object.freeze({applicationCursorKeys:!1,applicationKeypad:!1,bracketedPasteMode:!1,origin:!1,reverseWraparound:!1,sendFocus:!1,wraparound:!0});let d=t.CoreService=class extends a.Disposable{constructor(e,t,i){super(),this._bufferService=e,this._logService=t,this._optionsService=i,this.isCursorInitialized=!1,this.isCursorHidden=!1,this._onData=this.register(new o.EventEmitter),this.onData=this._onData.event,this._onUserInput=this.register(new o.EventEmitter),this.onUserInput=this._onUserInput.event,this._onBinary=this.register(new o.EventEmitter),this.onBinary=this._onBinary.event,this._onRequestScrollToBottom=this.register(new o.EventEmitter),this.onRequestScrollToBottom=this._onRequestScrollToBottom.event,this.modes=(0,n.clone)(c),this.decPrivateModes=(0,n.clone)(l)}reset(){this.modes=(0,n.clone)(c),this.decPrivateModes=(0,n.clone)(l)}triggerDataEvent(e,t=!1){if(this._optionsService.rawOptions.disableStdin)return;const i=this._bufferService.buffer;t&&this._optionsService.rawOptions.scrollOnUserInput&&i.ybase!==i.ydisp&&this._onRequestScrollToBottom.fire(),t&&this._onUserInput.fire(),this._logService.debug(`sending data "${e}"`,(()=>e.split("").map((e=>e.charCodeAt(0))))),this._onData.fire(e)}triggerBinaryEvent(e){this._optionsService.rawOptions.disableStdin||(this._logService.debug(`sending binary "${e}"`,(()=>e.split("").map((e=>e.charCodeAt(0))))),this._onBinary.fire(e))}};t.CoreService=d=s([r(0,h.IBufferService),r(1,h.ILogService),r(2,h.IOptionsService)],d)},9074:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DecorationService=void 0;const s=i(8055),r=i(8460),n=i(844),o=i(6106);let a=0,h=0;class c extends n.Disposable{get decorations(){return this._decorations.values()}constructor(){super(),this._decorations=new o.SortedList((e=>e?.marker.line)),this._onDecorationRegistered=this.register(new r.EventEmitter),this.onDecorationRegistered=this._onDecorationRegistered.event,this._onDecorationRemoved=this.register(new r.EventEmitter),this.onDecorationRemoved=this._onDecorationRemoved.event,this.register((0,n.toDisposable)((()=>this.reset())))}registerDecoration(e){if(e.marker.isDisposed)return;const t=new l(e);if(t){const e=t.marker.onDispose((()=>t.dispose()));t.onDispose((()=>{t&&(this._decorations.delete(t)&&this._onDecorationRemoved.fire(t),e.dispose())})),this._decorations.insert(t),this._onDecorationRegistered.fire(t)}return t}reset(){for(const e of this._decorations.values())e.dispose();this._decorations.clear()}*getDecorationsAtCell(e,t,i){let s=0,r=0;for(const n of this._decorations.getKeyIterator(t))s=n.options.x??0,r=s+(n.options.width??1),e>=s&&e{a=t.options.x??0,h=a+(t.options.width??1),e>=a&&e{Object.defineProperty(t,"__esModule",{value:!0}),t.InstantiationService=t.ServiceCollection=void 0;const s=i(2585),r=i(8343);class n{constructor(...e){this._entries=new Map;for(const[t,i]of e)this.set(t,i)}set(e,t){const i=this._entries.get(e);return this._entries.set(e,t),i}forEach(e){for(const[t,i]of this._entries.entries())e(t,i)}has(e){return this._entries.has(e)}get(e){return this._entries.get(e)}}t.ServiceCollection=n,t.InstantiationService=class{constructor(){this._services=new n,this._services.set(s.IInstantiationService,this)}setService(e,t){this._services.set(e,t)}getService(e){return this._services.get(e)}createInstance(e,...t){const i=(0,r.getServiceDependencies)(e).sort(((e,t)=>e.index-t.index)),s=[];for(const t of i){const i=this._services.get(t.id);if(!i)throw new Error(`[createInstance] ${e.name} depends on UNKNOWN service ${t.id}.`);s.push(i)}const n=i.length>0?i[0].index:t.length;if(t.length!==n)throw new Error(`[createInstance] First service dependency of ${e.name} at position ${n+1} conflicts with ${t.length} static arguments`);return new e(...[...t,...s])}}},7866:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.traceCall=t.setTraceLogger=t.LogService=void 0;const n=i(844),o=i(2585),a={trace:o.LogLevelEnum.TRACE,debug:o.LogLevelEnum.DEBUG,info:o.LogLevelEnum.INFO,warn:o.LogLevelEnum.WARN,error:o.LogLevelEnum.ERROR,off:o.LogLevelEnum.OFF};let h,c=t.LogService=class extends n.Disposable{get logLevel(){return this._logLevel}constructor(e){super(),this._optionsService=e,this._logLevel=o.LogLevelEnum.OFF,this._updateLogLevel(),this.register(this._optionsService.onSpecificOptionChange("logLevel",(()=>this._updateLogLevel()))),h=this}_updateLogLevel(){this._logLevel=a[this._optionsService.rawOptions.logLevel]}_evalLazyOptionalParams(e){for(let t=0;tJSON.stringify(e))).join(", ")})`);const t=s.apply(this,e);return h.trace(`GlyphRenderer#${s.name} return`,t),t}}},7302:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.OptionsService=t.DEFAULT_OPTIONS=void 0;const s=i(8460),r=i(844),n=i(6114);t.DEFAULT_OPTIONS={cols:80,rows:24,cursorBlink:!1,cursorStyle:"block",cursorWidth:1,cursorInactiveStyle:"outline",customGlyphs:!0,drawBoldTextInBrightColors:!0,documentOverride:null,fastScrollModifier:"alt",fastScrollSensitivity:5,fontFamily:"courier-new, courier, monospace",fontSize:15,fontWeight:"normal",fontWeightBold:"bold",ignoreBracketedPasteMode:!1,lineHeight:1,letterSpacing:0,linkHandler:null,logLevel:"info",logger:null,scrollback:1e3,scrollOnUserInput:!0,scrollSensitivity:1,screenReaderMode:!1,smoothScrollDuration:0,macOptionIsMeta:!1,macOptionClickForcesSelection:!1,minimumContrastRatio:1,disableStdin:!1,allowProposedApi:!1,allowTransparency:!1,tabStopWidth:8,theme:{},rescaleOverlappingGlyphs:!1,rightClickSelectsWord:n.isMac,windowOptions:{},windowsMode:!1,windowsPty:{},wordSeparator:" ()[]{}',\"`",altClickMovesCursor:!0,convertEol:!1,termName:"xterm",cancelEvents:!1,overviewRulerWidth:0};const o=["normal","bold","100","200","300","400","500","600","700","800","900"];class a extends r.Disposable{constructor(e){super(),this._onOptionChange=this.register(new s.EventEmitter),this.onOptionChange=this._onOptionChange.event;const i={...t.DEFAULT_OPTIONS};for(const t in e)if(t in i)try{const s=e[t];i[t]=this._sanitizeAndValidateOption(t,s)}catch(e){console.error(e)}this.rawOptions=i,this.options={...i},this._setupOptions(),this.register((0,r.toDisposable)((()=>{this.rawOptions.linkHandler=null,this.rawOptions.documentOverride=null})))}onSpecificOptionChange(e,t){return this.onOptionChange((i=>{i===e&&t(this.rawOptions[e])}))}onMultipleOptionChange(e,t){return this.onOptionChange((i=>{-1!==e.indexOf(i)&&t()}))}_setupOptions(){const e=e=>{if(!(e in t.DEFAULT_OPTIONS))throw new Error(`No option with key "${e}"`);return this.rawOptions[e]},i=(e,i)=>{if(!(e in t.DEFAULT_OPTIONS))throw new Error(`No option with key "${e}"`);i=this._sanitizeAndValidateOption(e,i),this.rawOptions[e]!==i&&(this.rawOptions[e]=i,this._onOptionChange.fire(e))};for(const t in this.rawOptions){const s={get:e.bind(this,t),set:i.bind(this,t)};Object.defineProperty(this.options,t,s)}}_sanitizeAndValidateOption(e,i){switch(e){case"cursorStyle":if(i||(i=t.DEFAULT_OPTIONS[e]),!function(e){return"block"===e||"underline"===e||"bar"===e}(i))throw new Error(`"${i}" is not a valid value for ${e}`);break;case"wordSeparator":i||(i=t.DEFAULT_OPTIONS[e]);break;case"fontWeight":case"fontWeightBold":if("number"==typeof i&&1<=i&&i<=1e3)break;i=o.includes(i)?i:t.DEFAULT_OPTIONS[e];break;case"cursorWidth":i=Math.floor(i);case"lineHeight":case"tabStopWidth":if(i<1)throw new Error(`${e} cannot be less than 1, value: ${i}`);break;case"minimumContrastRatio":i=Math.max(1,Math.min(21,Math.round(10*i)/10));break;case"scrollback":if((i=Math.min(i,4294967295))<0)throw new Error(`${e} cannot be less than 0, value: ${i}`);break;case"fastScrollSensitivity":case"scrollSensitivity":if(i<=0)throw new Error(`${e} cannot be less than or equal to 0, value: ${i}`);break;case"rows":case"cols":if(!i&&0!==i)throw new Error(`${e} must be numeric, value: ${i}`);break;case"windowsPty":i=i??{}}return i}}t.OptionsService=a},2660:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OscLinkService=void 0;const n=i(2585);let o=t.OscLinkService=class{constructor(e){this._bufferService=e,this._nextId=1,this._entriesWithId=new Map,this._dataByLinkId=new Map}registerLink(e){const t=this._bufferService.buffer;if(void 0===e.id){const i=t.addMarker(t.ybase+t.y),s={data:e,id:this._nextId++,lines:[i]};return i.onDispose((()=>this._removeMarkerFromLink(s,i))),this._dataByLinkId.set(s.id,s),s.id}const i=e,s=this._getEntryIdKey(i),r=this._entriesWithId.get(s);if(r)return this.addLineToLink(r.id,t.ybase+t.y),r.id;const n=t.addMarker(t.ybase+t.y),o={id:this._nextId++,key:this._getEntryIdKey(i),data:i,lines:[n]};return n.onDispose((()=>this._removeMarkerFromLink(o,n))),this._entriesWithId.set(o.key,o),this._dataByLinkId.set(o.id,o),o.id}addLineToLink(e,t){const i=this._dataByLinkId.get(e);if(i&&i.lines.every((e=>e.line!==t))){const e=this._bufferService.buffer.addMarker(t);i.lines.push(e),e.onDispose((()=>this._removeMarkerFromLink(i,e)))}}getLinkData(e){return this._dataByLinkId.get(e)?.data}_getEntryIdKey(e){return`${e.id};;${e.uri}`}_removeMarkerFromLink(e,t){const i=e.lines.indexOf(t);-1!==i&&(e.lines.splice(i,1),0===e.lines.length&&(void 0!==e.data.id&&this._entriesWithId.delete(e.key),this._dataByLinkId.delete(e.id)))}};t.OscLinkService=o=s([r(0,n.IBufferService)],o)},8343:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createDecorator=t.getServiceDependencies=t.serviceRegistry=void 0;const i="di$target",s="di$dependencies";t.serviceRegistry=new Map,t.getServiceDependencies=function(e){return e[s]||[]},t.createDecorator=function(e){if(t.serviceRegistry.has(e))return t.serviceRegistry.get(e);const r=function(e,t,n){if(3!==arguments.length)throw new Error("@IServiceName-decorator can only be used to decorate a parameter");!function(e,t,r){t[i]===t?t[s].push({id:e,index:r}):(t[s]=[{id:e,index:r}],t[i]=t)}(r,e,n)};return r.toString=()=>e,t.serviceRegistry.set(e,r),r}},2585:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.IDecorationService=t.IUnicodeService=t.IOscLinkService=t.IOptionsService=t.ILogService=t.LogLevelEnum=t.IInstantiationService=t.ICharsetService=t.ICoreService=t.ICoreMouseService=t.IBufferService=void 0;const s=i(8343);var r;t.IBufferService=(0,s.createDecorator)("BufferService"),t.ICoreMouseService=(0,s.createDecorator)("CoreMouseService"),t.ICoreService=(0,s.createDecorator)("CoreService"),t.ICharsetService=(0,s.createDecorator)("CharsetService"),t.IInstantiationService=(0,s.createDecorator)("InstantiationService"),function(e){e[e.TRACE=0]="TRACE",e[e.DEBUG=1]="DEBUG",e[e.INFO=2]="INFO",e[e.WARN=3]="WARN",e[e.ERROR=4]="ERROR",e[e.OFF=5]="OFF"}(r||(t.LogLevelEnum=r={})),t.ILogService=(0,s.createDecorator)("LogService"),t.IOptionsService=(0,s.createDecorator)("OptionsService"),t.IOscLinkService=(0,s.createDecorator)("OscLinkService"),t.IUnicodeService=(0,s.createDecorator)("UnicodeService"),t.IDecorationService=(0,s.createDecorator)("DecorationService")},1480:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeService=void 0;const s=i(8460),r=i(225);class n{static extractShouldJoin(e){return 0!=(1&e)}static extractWidth(e){return e>>1&3}static extractCharKind(e){return e>>3}static createPropertyValue(e,t,i=!1){return(16777215&e)<<3|(3&t)<<1|(i?1:0)}constructor(){this._providers=Object.create(null),this._active="",this._onChange=new s.EventEmitter,this.onChange=this._onChange.event;const e=new r.UnicodeV6;this.register(e),this._active=e.version,this._activeProvider=e}dispose(){this._onChange.dispose()}get versions(){return Object.keys(this._providers)}get activeVersion(){return this._active}set activeVersion(e){if(!this._providers[e])throw new Error(`unknown Unicode version "${e}"`);this._active=e,this._activeProvider=this._providers[e],this._onChange.fire(e)}register(e){this._providers[e.version]=e}wcwidth(e){return this._activeProvider.wcwidth(e)}getStringCellWidth(e){let t=0,i=0;const s=e.length;for(let r=0;r=s)return t+this.wcwidth(o);const i=e.charCodeAt(r);56320<=i&&i<=57343?o=1024*(o-55296)+i-56320+65536:t+=this.wcwidth(i)}const a=this.charProperties(o,i);let h=n.extractWidth(a);n.extractShouldJoin(a)&&(h-=n.extractWidth(i)),t+=h,i=a}return t}charProperties(e,t){return this._activeProvider.charProperties(e,t)}}t.UnicodeService=n}},t={};function i(s){var r=t[s];if(void 0!==r)return r.exports;var n=t[s]={exports:{}};return e[s].call(n.exports,n,n.exports,i),n.exports}var s={};return(()=>{var e=s;Object.defineProperty(e,"__esModule",{value:!0}),e.Terminal=void 0;const t=i(9042),r=i(3236),n=i(844),o=i(5741),a=i(8285),h=i(7975),c=i(7090),l=["cols","rows"];class d extends n.Disposable{constructor(e){super(),this._core=this.register(new r.Terminal(e)),this._addonManager=this.register(new o.AddonManager),this._publicOptions={...this._core.options};const t=e=>this._core.options[e],i=(e,t)=>{this._checkReadonlyOptions(e),this._core.options[e]=t};for(const e in this._core.options){const s={get:t.bind(this,e),set:i.bind(this,e)};Object.defineProperty(this._publicOptions,e,s)}}_checkReadonlyOptions(e){if(l.includes(e))throw new Error(`Option "${e}" can only be set in the constructor`)}_checkProposedApi(){if(!this._core.optionsService.rawOptions.allowProposedApi)throw new Error("You must set the allowProposedApi option to true to use proposed API")}get onBell(){return this._core.onBell}get onBinary(){return this._core.onBinary}get onCursorMove(){return this._core.onCursorMove}get onData(){return this._core.onData}get onKey(){return this._core.onKey}get onLineFeed(){return this._core.onLineFeed}get onRender(){return this._core.onRender}get onResize(){return this._core.onResize}get onScroll(){return this._core.onScroll}get onSelectionChange(){return this._core.onSelectionChange}get onTitleChange(){return this._core.onTitleChange}get onWriteParsed(){return this._core.onWriteParsed}get element(){return this._core.element}get parser(){return this._parser||(this._parser=new h.ParserApi(this._core)),this._parser}get unicode(){return this._checkProposedApi(),new c.UnicodeApi(this._core)}get textarea(){return this._core.textarea}get rows(){return this._core.rows}get cols(){return this._core.cols}get buffer(){return this._buffer||(this._buffer=this.register(new a.BufferNamespaceApi(this._core))),this._buffer}get markers(){return this._checkProposedApi(),this._core.markers}get modes(){const e=this._core.coreService.decPrivateModes;let t="none";switch(this._core.coreMouseService.activeProtocol){case"X10":t="x10";break;case"VT200":t="vt200";break;case"DRAG":t="drag";break;case"ANY":t="any"}return{applicationCursorKeysMode:e.applicationCursorKeys,applicationKeypadMode:e.applicationKeypad,bracketedPasteMode:e.bracketedPasteMode,insertMode:this._core.coreService.modes.insertMode,mouseTrackingMode:t,originMode:e.origin,reverseWraparoundMode:e.reverseWraparound,sendFocusMode:e.sendFocus,wraparoundMode:e.wraparound}}get options(){return this._publicOptions}set options(e){for(const t in e)this._publicOptions[t]=e[t]}blur(){this._core.blur()}focus(){this._core.focus()}input(e,t=!0){this._core.input(e,t)}resize(e,t){this._verifyIntegers(e,t),this._core.resize(e,t)}open(e){this._core.open(e)}attachCustomKeyEventHandler(e){this._core.attachCustomKeyEventHandler(e)}attachCustomWheelEventHandler(e){this._core.attachCustomWheelEventHandler(e)}registerLinkProvider(e){return this._core.registerLinkProvider(e)}registerCharacterJoiner(e){return this._checkProposedApi(),this._core.registerCharacterJoiner(e)}deregisterCharacterJoiner(e){this._checkProposedApi(),this._core.deregisterCharacterJoiner(e)}registerMarker(e=0){return this._verifyIntegers(e),this._core.registerMarker(e)}registerDecoration(e){return this._checkProposedApi(),this._verifyPositiveIntegers(e.x??0,e.width??0,e.height??0),this._core.registerDecoration(e)}hasSelection(){return this._core.hasSelection()}select(e,t,i){this._verifyIntegers(e,t,i),this._core.select(e,t,i)}getSelection(){return this._core.getSelection()}getSelectionPosition(){return this._core.getSelectionPosition()}clearSelection(){this._core.clearSelection()}selectAll(){this._core.selectAll()}selectLines(e,t){this._verifyIntegers(e,t),this._core.selectLines(e,t)}dispose(){super.dispose()}scrollLines(e){this._verifyIntegers(e),this._core.scrollLines(e)}scrollPages(e){this._verifyIntegers(e),this._core.scrollPages(e)}scrollToTop(){this._core.scrollToTop()}scrollToBottom(){this._core.scrollToBottom()}scrollToLine(e){this._verifyIntegers(e),this._core.scrollToLine(e)}clear(){this._core.clear()}write(e,t){this._core.write(e,t)}writeln(e,t){this._core.write(e),this._core.write("\r\n",t)}paste(e){this._core.paste(e)}refresh(e,t){this._verifyIntegers(e,t),this._core.refresh(e,t)}reset(){this._core.reset()}clearTextureAtlas(){this._core.clearTextureAtlas()}loadAddon(e){this._addonManager.loadAddon(this,e)}static get strings(){return t}_verifyIntegers(...e){for(const t of e)if(t===1/0||isNaN(t)||t%1!=0)throw new Error("This API only accepts integers")}_verifyPositiveIntegers(...e){for(const t of e)if(t&&(t===1/0||isNaN(t)||t%1!=0||t<0))throw new Error("This API only accepts positive integers")}}e.Terminal=d})(),s})())); +//# sourceMappingURL=xterm.js.map \ No newline at end of file diff --git a/root/usr/share/openclaw/web-pty.js b/root/usr/share/openclaw/web-pty.js new file mode 100644 index 0000000..28b415e --- /dev/null +++ b/root/usr/share/openclaw/web-pty.js @@ -0,0 +1,285 @@ +#!/usr/bin/env node +// ============================================================================ +// OpenClaw 配置工具 — Web PTY 服务器 +// 纯 Node.js 实现,零外部依赖 +// 通过 WebSocket 将 oc-config.sh 的 TTY 输出推送给浏览器 xterm.js +// HTTP 端口 18793, HTTPS 可选端口 18794 +// ============================================================================ + +const http = require('http'); +const https = require('https'); +const crypto = require('crypto'); +const { spawn } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const os = require('os'); + +// ── 配置 (OpenWrt 适配) ── +const PORT = parseInt(process.env.OC_CONFIG_PORT || '18793', 10); +const HOST = process.env.OC_CONFIG_HOST || '0.0.0.0'; // token 认证保护,可安全绑定所有接口 +const NODE_BASE = process.env.NODE_BASE || '/opt/openclaw/node'; +const OC_GLOBAL = process.env.OC_GLOBAL || '/opt/openclaw/global'; +const OC_DATA = process.env.OC_DATA || '/opt/openclaw/data'; +const SCRIPT_PATH = process.env.OC_CONFIG_SCRIPT || '/usr/share/openclaw/oc-config.sh'; +const SSL_CERT = '/etc/uhttpd.crt'; +const SSL_KEY = '/etc/uhttpd.key'; +const MAX_SESSIONS = parseInt(process.env.OC_MAX_SESSIONS || '5', 10); + +// ── 认证令牌 (从 UCI 或环境变量读取) ── +function loadAuthToken() { + try { + const { execSync } = require('child_process'); + const t = execSync('uci -q get openclaw.main.luci_token 2>/dev/null', { encoding: 'utf8', timeout: 3000 }).trim(); + return t || ''; + } catch { return ''; } +} +let AUTH_TOKEN = process.env.OC_PTY_TOKEN || loadAuthToken(); + +// ── 会话计数 ── +let activeSessions = 0; + +// ── 静态文件 ── +const UI_DIR = path.join(__dirname, 'ui'); + +function getMimeType(ext) { + const types = { + '.html': 'text/html; charset=utf-8', '.css': 'text/css', + '.js': 'application/javascript', '.png': 'image/png', + '.svg': 'image/svg+xml', '.ico': 'image/x-icon', '.json': 'application/json', + }; + return types[ext] || 'application/octet-stream'; +} + +const IFRAME_HEADERS = { + 'Access-Control-Allow-Origin': '*', + 'X-Frame-Options': 'ALLOWALL', + 'Content-Security-Policy': "default-src * 'unsafe-inline' 'unsafe-eval' data: blob: ws: wss:; frame-ancestors *", +}; + +// ── WebSocket 帧处理 (RFC 6455) ── +function decodeWSFrame(buf) { + if (buf.length < 2) return null; + const opcode = buf[0] & 0x0f; + const masked = !!(buf[1] & 0x80); + let payloadLen = buf[1] & 0x7f; + let offset = 2; + if (payloadLen === 126) { + if (buf.length < 4) return null; + payloadLen = buf.readUInt16BE(2); offset = 4; + } else if (payloadLen === 127) { + if (buf.length < 10) return null; + payloadLen = Number(buf.readBigUInt64BE(2)); offset = 10; + } + let mask = null; + if (masked) { + if (buf.length < offset + 4) return null; + mask = buf.slice(offset, offset + 4); offset += 4; + } + if (buf.length < offset + payloadLen) return null; + const data = buf.slice(offset, offset + payloadLen); + if (mask) { for (let i = 0; i < data.length; i++) data[i] ^= mask[i & 3]; } + return { opcode, data, totalLen: offset + payloadLen }; +} + +function encodeWSFrame(data, opcode = 0x01) { + const payload = typeof data === 'string' ? Buffer.from(data) : data; + const len = payload.length; + let header; + if (len < 126) { + header = Buffer.alloc(2); header[0] = 0x80 | opcode; header[1] = len; + } else if (len < 65536) { + header = Buffer.alloc(4); header[0] = 0x80 | opcode; header[1] = 126; header.writeUInt16BE(len, 2); + } else { + header = Buffer.alloc(10); header[0] = 0x80 | opcode; header[1] = 127; header.writeBigUInt64BE(BigInt(len), 2); + } + return Buffer.concat([header, payload]); +} + +// ── PTY 进程管理 ── +class PtySession { + constructor(socket) { + this.socket = socket; + this.proc = null; + this.cols = 80; + this.rows = 24; + this.buffer = Buffer.alloc(0); + this.alive = true; + activeSessions++; + console.log(`[oc-config] Session created (active: ${activeSessions}/${MAX_SESSIONS})`); + this._setupWSReader(); + this._spawnPty(); + } + + _setupWSReader() { + this.socket.on('data', (chunk) => { + this.buffer = Buffer.concat([this.buffer, chunk]); + while (this.buffer.length > 0) { + const frame = decodeWSFrame(this.buffer); + if (!frame) break; + this.buffer = this.buffer.slice(frame.totalLen); + if (frame.opcode === 0x01) this._handleMessage(frame.data.toString()); + else if (frame.opcode === 0x02 && this.proc && this.proc.stdin.writable) this.proc.stdin.write(frame.data); + else if (frame.opcode === 0x08) { console.log('[oc-config] WS close frame received'); this._cleanup(); } + else if (frame.opcode === 0x09) this.socket.write(encodeWSFrame(frame.data, 0x0a)); + } + }); + this.socket.on('close', (hadError) => { console.log(`[oc-config] Socket closed, hadError=${hadError}`); this._cleanup(); }); + this.socket.on('error', (err) => { console.log(`[oc-config] Socket error: ${err.message}`); this._cleanup(); }); + } + + _handleMessage(text) { + try { + const msg = JSON.parse(text); + if (msg.type === 'stdin' && this.proc && this.proc.stdin.writable) { + // 去除 bracketed paste 转义序列,避免污染 shell read 输入 + const cleaned = msg.data.replace(/\x1b\[\?2004[hl]/g, '').replace(/\x1b\[20[01]~/g, ''); + this.proc.stdin.write(cleaned); + } + else if (msg.type === 'resize') { + this.cols = msg.cols || 80; this.rows = msg.rows || 24; + if (this.proc && this.proc.pid) { try { process.kill(-this.proc.pid, 'SIGWINCH'); } catch(e){} } + } + } catch(e) { if (this.proc && this.proc.stdin.writable) this.proc.stdin.write(text); } + } + + _spawnPty() { + const env = { + ...process.env, TERM: 'xterm-256color', COLUMNS: String(this.cols), LINES: String(this.rows), + COLORTERM: 'truecolor', LANG: 'en_US.UTF-8', + NODE_BASE, OC_GLOBAL, OC_DATA, + HOME: OC_DATA, + OPENCLAW_HOME: OC_DATA, + OPENCLAW_STATE_DIR: `${OC_DATA}/.openclaw`, + OPENCLAW_CONFIG_PATH: `${OC_DATA}/.openclaw/openclaw.json`, + PATH: `${NODE_BASE}/bin:${OC_GLOBAL}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, + }; + this.proc = spawn('script', ['-qc', `stty rows ${this.rows} cols ${this.cols} 2>/dev/null; printf '\\e[?2004l'; sh "${SCRIPT_PATH}"`, '/dev/null'], + { stdio: ['pipe', 'pipe', 'pipe'], env, detached: true }); + + this.proc.stdout.on('data', (d) => { if (this.alive) this.socket.write(encodeWSFrame(d, 0x01)); }); + this.proc.stderr.on('data', (d) => { if (this.alive) this.socket.write(encodeWSFrame(d, 0x01)); }); + this.proc.on('close', (code) => { + if (!this.alive) return; + console.log(`[oc-config] Script exited with code ${code}, auto-restarting...`); + this.socket.write(encodeWSFrame(`\r\n\x1b[33m配置脚本已退出 (code: ${code}),正在自动重启...\x1b[0m\r\n`, 0x01)); + this.proc = null; + // 自动重启脚本,保持 WebSocket 连接 + setTimeout(() => { + if (this.alive) { + this._spawnPty(); + } + }, 1500); + }); + this.proc.on('error', (err) => { + if (this.alive) this.socket.write(encodeWSFrame(`\r\n\x1b[31m启动失败: ${err.message}\x1b[0m\r\n`, 0x01)); + }); + } + + _cleanup() { + if (!this.alive) return; this.alive = false; + activeSessions = Math.max(0, activeSessions - 1); + console.log(`[oc-config] Session ended (active: ${activeSessions}/${MAX_SESSIONS})`); + if (this.proc) { try { process.kill(-this.proc.pid, 'SIGTERM'); } catch(e){} try { this.proc.kill('SIGTERM'); } catch(e){} } + try { this.socket.destroy(); } catch(e){} + } +} + +// ── HTTP 请求处理 ── +function handleRequest(req, res) { + const url = new URL(req.url, `http://${req.headers.host}`); + let fp = url.pathname; + + if (req.method === 'OPTIONS') { + res.writeHead(204, { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, OPTIONS', 'Access-Control-Allow-Headers': '*' }); + return res.end(); + } + if (fp === '/health') { + res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }); + return res.end(JSON.stringify({ status: 'ok', port: PORT, uptime: process.uptime() })); + } + if (fp === '/' || fp === '') fp = '/index.html'; + + const fullPath = path.join(UI_DIR, fp); + if (!fullPath.startsWith(UI_DIR)) { res.writeHead(403); return res.end('Forbidden'); } + + fs.readFile(fullPath, (err, data) => { + if (err) { + if (fp !== '/index.html') { + fs.readFile(path.join(UI_DIR, 'index.html'), (e2, d2) => { + if (e2) { res.writeHead(404); res.end('Not Found'); } + else { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', ...IFRAME_HEADERS }); res.end(d2); } + }); + } else { res.writeHead(404); res.end('Not Found'); } + return; + } + const ext = path.extname(fullPath); + res.writeHead(200, { 'Content-Type': getMimeType(ext), 'Cache-Control': ext === '.html' ? 'no-cache' : 'max-age=3600', ...IFRAME_HEADERS }); + res.end(data); + }); +} + +// ── WebSocket Upgrade ── +function handleUpgrade(req, socket, head) { + console.log(`[oc-config] WS upgrade: ${req.url} remote=${socket.remoteAddress}:${socket.remotePort}`); + if (req.url !== '/ws' && !req.url.startsWith('/ws?')) { socket.destroy(); return; } + + // 认证: 验证查询参数中的 token + if (AUTH_TOKEN) { + const url = new URL(req.url, `http://${req.headers.host || 'localhost'}`); + const clientToken = url.searchParams.get('token') || ''; + if (clientToken !== AUTH_TOKEN) { + console.log(`[oc-config] WS auth failed from ${socket.remoteAddress}`); + socket.write('HTTP/1.1 403 Forbidden\r\n\r\n'); + socket.destroy(); + return; + } + } + + // 并发会话限制 + if (activeSessions >= MAX_SESSIONS) { + console.log(`[oc-config] Max sessions reached (${activeSessions}/${MAX_SESSIONS}), rejecting`); + socket.write('HTTP/1.1 503 Service Unavailable\r\n\r\n'); + socket.destroy(); + return; + } + + const key = req.headers['sec-websocket-key']; + if (!key) { console.log('[oc-config] Missing Sec-WebSocket-Key'); socket.destroy(); return; } + + const accept = crypto.createHash('sha1').update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11').digest('base64'); + + socket.setNoDelay(true); + socket.setTimeout(0); + + const handshake = 'HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ' + accept + '\r\n\r\n'; + + socket.write(handshake, () => { + if (head && head.length > 0) socket.unshift(head); + new PtySession(socket); + console.log('[oc-config] PTY session started'); + }); +} + +// ── 服务器实例 ── +const httpServer = http.createServer(handleRequest); +httpServer.on('upgrade', handleUpgrade); + +httpServer.listen(PORT, HOST, () => { + console.log(`[oc-config] HTTP listening on ${HOST}:${PORT}`); + console.log(`[oc-config] Script: ${SCRIPT_PATH}`); +}); + +// HTTPS 可选端口 PORT+1 +const HTTPS_PORT = PORT + 1; +try { + if (fs.existsSync(SSL_CERT) && fs.existsSync(SSL_KEY)) { + const httpsServer = https.createServer({ cert: fs.readFileSync(SSL_CERT), key: fs.readFileSync(SSL_KEY) }, handleRequest); + httpsServer.on('upgrade', handleUpgrade); + httpsServer.listen(HTTPS_PORT, HOST, () => console.log(`[oc-config] HTTPS listening on ${HOST}:${HTTPS_PORT}`)); + httpsServer.on('error', (e) => console.log(`[oc-config] HTTPS port ${HTTPS_PORT}: ${e.message}`)); + } +} catch (e) { console.log(`[oc-config] SSL init: ${e.message}`); } + +httpServer.on('error', (e) => { console.error(`[oc-config] Fatal: ${e.message}`); process.exit(1); }); +process.on('SIGTERM', () => { console.log('[oc-config] Shutdown'); httpServer.close(); process.exit(0); }); +process.on('SIGINT', () => { httpServer.close(); process.exit(0); }); diff --git a/scripts/build_ipk.sh b/scripts/build_ipk.sh new file mode 100755 index 0000000..b6042a6 --- /dev/null +++ b/scripts/build_ipk.sh @@ -0,0 +1,143 @@ +#!/bin/sh +# ============================================================================ +# 本地构建 .ipk 包 (无需 OpenWrt SDK) +# 用法: sh scripts/build_ipk.sh [output_dir] +# ============================================================================ +set -e + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +PKG_DIR=$(cd "$SCRIPT_DIR/.." && pwd) +OUT_DIR="${1:-$PKG_DIR/dist}" +# 确保 OUT_DIR 是绝对路径 +case "$OUT_DIR" in + /*) ;; + *) OUT_DIR="$PKG_DIR/$OUT_DIR" ;; +esac +mkdir -p "$OUT_DIR" +PKG_NAME="luci-app-openclaw" +PKG_VERSION=$(cat "$PKG_DIR/VERSION" 2>/dev/null | tr -d '[:space:]' || echo "1.0.0") +PKG_RELEASE="1" + +echo "=== 构建 ${PKG_NAME} .ipk 包 ===" + +STAGING=$(mktemp -d) +trap "rm -rf '$STAGING'" EXIT + +# ── 构建 data.tar.gz ── +DATA_DIR="$STAGING/data" +mkdir -p "$DATA_DIR" + +# UCI config +mkdir -p "$DATA_DIR/etc/config" +cp "$PKG_DIR/root/etc/config/openclaw" "$DATA_DIR/etc/config/" + +# UCI defaults +mkdir -p "$DATA_DIR/etc/uci-defaults" +cp "$PKG_DIR/root/etc/uci-defaults/99-openclaw" "$DATA_DIR/etc/uci-defaults/" +chmod +x "$DATA_DIR/etc/uci-defaults/99-openclaw" + +# init.d +mkdir -p "$DATA_DIR/etc/init.d" +cp "$PKG_DIR/root/etc/init.d/openclaw" "$DATA_DIR/etc/init.d/" +chmod +x "$DATA_DIR/etc/init.d/openclaw" + +# bin +mkdir -p "$DATA_DIR/usr/bin" +cp "$PKG_DIR/root/usr/bin/openclaw-env" "$DATA_DIR/usr/bin/" +chmod +x "$DATA_DIR/usr/bin/openclaw-env" + +# LuCI controller +mkdir -p "$DATA_DIR/usr/lib/lua/luci/controller" +cp "$PKG_DIR/luasrc/controller/openclaw.lua" "$DATA_DIR/usr/lib/lua/luci/controller/" + +# LuCI CBI +mkdir -p "$DATA_DIR/usr/lib/lua/luci/model/cbi/openclaw" +cp "$PKG_DIR/luasrc/model/cbi/openclaw/"*.lua "$DATA_DIR/usr/lib/lua/luci/model/cbi/openclaw/" + +# LuCI views +mkdir -p "$DATA_DIR/usr/lib/lua/luci/view/openclaw" +cp "$PKG_DIR/luasrc/view/openclaw/"*.htm "$DATA_DIR/usr/lib/lua/luci/view/openclaw/" + +# oc-config assets +mkdir -p "$DATA_DIR/usr/share/openclaw" +cp "$PKG_DIR/root/usr/share/openclaw/oc-config.sh" "$DATA_DIR/usr/share/openclaw/" +chmod +x "$DATA_DIR/usr/share/openclaw/oc-config.sh" +cp "$PKG_DIR/root/usr/share/openclaw/web-pty.js" "$DATA_DIR/usr/share/openclaw/" + +# Web PTY UI +cp -r "$PKG_DIR/root/usr/share/openclaw/ui" "$DATA_DIR/usr/share/openclaw/" + +# i18n (po2lmo 可选) +mkdir -p "$DATA_DIR/usr/lib/lua/luci/i18n" +if command -v po2lmo >/dev/null 2>&1 && [ -f "$PKG_DIR/po/zh-cn/openclaw.po" ]; then + po2lmo "$PKG_DIR/po/zh-cn/openclaw.po" "$DATA_DIR/usr/lib/lua/luci/i18n/openclaw.zh-cn.lmo" 2>/dev/null || true +fi + +# 计算安装大小 +INSTALLED_SIZE=$(du -sk "$DATA_DIR" | awk '{print $1}') + +(cd "$DATA_DIR" && tar czf "$STAGING/data.tar.gz" .) + +# ── 构建 control.tar.gz ── +CTRL_DIR="$STAGING/control" +mkdir -p "$CTRL_DIR" + +cat > "$CTRL_DIR/control" << EOF +Package: ${PKG_NAME} +Version: ${PKG_VERSION}-${PKG_RELEASE} +Depends: luci-compat, luci-base, curl, openssl-util +Source: https://github.com/10000ge10000/luci-app-openclaw +SourceName: ${PKG_NAME} +License: GPL-3.0 +Section: luci +SourceDateEpoch: $(date +%s) +Maintainer: 10000ge10000 <10000ge10000@users.noreply.github.com> +Architecture: all +Installed-Size: ${INSTALLED_SIZE} +Description: OpenClaw AI 网关 LuCI 管理插件 +EOF + +cat > "$CTRL_DIR/postinst" << 'EOF' +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/99-openclaw ) && rm -f /etc/uci-defaults/99-openclaw + rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* 2>/dev/null + exit 0 +} +EOF +chmod +x "$CTRL_DIR/postinst" + +cat > "$CTRL_DIR/postrm" << 'EOF' +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* 2>/dev/null +} +EOF +chmod +x "$CTRL_DIR/postrm" + +cat > "$CTRL_DIR/conffiles" << 'EOF' +/etc/config/openclaw +EOF + +(cd "$CTRL_DIR" && tar czf "$STAGING/control.tar.gz" .) + +# ── 组装 .ipk (ar 格式) ── +mkdir -p "$OUT_DIR" +IPK_FILE="$OUT_DIR/${PKG_NAME}_${PKG_VERSION}-${PKG_RELEASE}_all.ipk" + +echo "2.0" > "$STAGING/debian-binary" + +# 清理旧文件 +rm -f "$IPK_FILE" + +# 组装 .ipk — OpenWrt opkg 使用 tar.gz 格式 (非 Debian 的 ar 格式) +(cd "$STAGING" && tar czf "$IPK_FILE" debian-binary control.tar.gz data.tar.gz) + +IPK_SIZE=$(wc -c < "$IPK_FILE" | tr -d ' ') +echo "" +echo "=== 构建完成 ===" +echo "输出文件: $IPK_FILE" +echo "文件大小: ${IPK_SIZE} bytes" +echo "安装大小: ${INSTALLED_SIZE} KB" +echo "" +echo "安装方法: opkg install ${PKG_NAME}_${PKG_VERSION}-${PKG_RELEASE}_all.ipk" diff --git a/scripts/build_run.sh b/scripts/build_run.sh new file mode 100755 index 0000000..079f86f --- /dev/null +++ b/scripts/build_run.sh @@ -0,0 +1,235 @@ +#!/bin/sh +# ============================================================================ +# iStoreOS .run 自解压包构建脚本 +# 用法: sh scripts/build_run.sh [output_dir] +# ============================================================================ +set -e + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +PKG_DIR=$(cd "$SCRIPT_DIR/.." && pwd) +OUT_DIR="${1:-$PKG_DIR/dist}" +# 确保 OUT_DIR 是绝对路径 +case "$OUT_DIR" in + /*) ;; + *) OUT_DIR="$PKG_DIR/$OUT_DIR" ;; +esac +mkdir -p "$OUT_DIR" +PKG_NAME="luci-app-openclaw" +PKG_VERSION=$(cat "$PKG_DIR/VERSION" 2>/dev/null | tr -d '[:space:]' || echo "1.0.0") + +echo "=== 构建 iStoreOS .run 安装包 ===" +echo "源目录: $PKG_DIR" +echo "输出到: $OUT_DIR" + +# 创建临时打包目录 +STAGING=$(mktemp -d) +trap "rm -rf '$STAGING'" EXIT + +# 安装文件到暂存区 +install_files() { + local dest="$1" + + # UCI config + mkdir -p "$dest/etc/config" + cp "$PKG_DIR/root/etc/config/openclaw" "$dest/etc/config/" + + # UCI defaults + mkdir -p "$dest/etc/uci-defaults" + cp "$PKG_DIR/root/etc/uci-defaults/99-openclaw" "$dest/etc/uci-defaults/" + chmod +x "$dest/etc/uci-defaults/99-openclaw" + + # init.d + mkdir -p "$dest/etc/init.d" + cp "$PKG_DIR/root/etc/init.d/openclaw" "$dest/etc/init.d/" + chmod +x "$dest/etc/init.d/openclaw" + + # bin + mkdir -p "$dest/usr/bin" + cp "$PKG_DIR/root/usr/bin/openclaw-env" "$dest/usr/bin/" + chmod +x "$dest/usr/bin/openclaw-env" + + # LuCI controller + mkdir -p "$dest/usr/lib/lua/luci/controller" + cp "$PKG_DIR/luasrc/controller/openclaw.lua" "$dest/usr/lib/lua/luci/controller/" + + # LuCI CBI + mkdir -p "$dest/usr/lib/lua/luci/model/cbi/openclaw" + cp "$PKG_DIR/luasrc/model/cbi/openclaw/"*.lua "$dest/usr/lib/lua/luci/model/cbi/openclaw/" + + # LuCI views + mkdir -p "$dest/usr/lib/lua/luci/view/openclaw" + cp "$PKG_DIR/luasrc/view/openclaw/"*.htm "$dest/usr/lib/lua/luci/view/openclaw/" + + # oc-config assets + mkdir -p "$dest/usr/share/openclaw" + cp "$PKG_DIR/root/usr/share/openclaw/oc-config.sh" "$dest/usr/share/openclaw/" + chmod +x "$dest/usr/share/openclaw/oc-config.sh" + cp "$PKG_DIR/root/usr/share/openclaw/web-pty.js" "$dest/usr/share/openclaw/" + + # Web PTY UI (recursive copy) + cp -r "$PKG_DIR/root/usr/share/openclaw/ui" "$dest/usr/share/openclaw/" +} + +# 创建安装器脚本头部 +create_installer() { + cat > "$STAGING/install.sh" << 'INSTALLER_EOF' +#!/bin/sh +# luci-app-openclaw iStoreOS 安装器 +set -e + +echo "╔══════════════════════════════════════════════════════════════╗" +echo "║ luci-app-openclaw — OpenClaw AI Gateway 插件 ║" +echo "╚══════════════════════════════════════════════════════════════╝" +echo "" + +# 检查系统 +if [ ! -f /etc/openwrt_release ]; then + echo "错误: 此安装包仅适用于 OpenWrt/iStoreOS 系统" + exit 1 +fi + +# 检查架构 +ARCH=$(uname -m) +case "$ARCH" in + x86_64|aarch64) ;; + *) echo "错误: 不支持的架构 $ARCH (仅支持 x86_64/aarch64)"; exit 1 ;; +esac + +# 检查依赖 +for dep in luci-compat luci-base; do + if ! opkg list-installed 2>/dev/null | grep -q "^${dep} "; then + echo "警告: 缺少依赖 $dep,尝试安装..." + opkg update >/dev/null 2>&1 || true + opkg install "$dep" 2>/dev/null || echo " 安装 $dep 失败,请手动安装" + fi +done + +echo "正在安装文件..." + +# 解压 payload (从 MARKER 行之后) +ARCHIVE=$(awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0; }' "$0") +tail -n +$ARCHIVE "$0" | tar xzf - -C / 2>/dev/null + +# 注册到 opkg,使 iStore 和 opkg 能识别此包 +PKG="luci-app-openclaw" +PKG_VER="__PKG_VERSION__" +INFO_DIR="/usr/lib/opkg/info" +STATUS_FILE="/usr/lib/opkg/status" +INSTALL_TIME=$(date +%s) + +mkdir -p "$INFO_DIR" + +# 写入 control 文件 +cat > "$INFO_DIR/$PKG.control" << CTLEOF +Package: $PKG +Version: $PKG_VER +Depends: luci-compat, luci-base, curl, openssl-util +Section: luci +Architecture: all +Installed-Size: 0 +Description: OpenClaw AI Gateway — LuCI 界面 +CTLEOF + +# 写入文件列表 (payload 中已安装的文件) +cat > "$INFO_DIR/$PKG.list" << LISTEOF +__FILE_LIST__ +LISTEOF + +# 写入 prerm 脚本 (卸载前执行) +cat > "$INFO_DIR/$PKG.prerm" << 'RMEOF' +#!/bin/sh +/etc/init.d/openclaw stop 2>/dev/null +/etc/init.d/openclaw disable 2>/dev/null +exit 0 +RMEOF +chmod +x "$INFO_DIR/$PKG.prerm" + +# 追加到 opkg status 数据库 (先移除旧记录) +if [ -f "$STATUS_FILE" ]; then + awk -v pkg="$PKG" ' + BEGIN { skip=0 } + /^Package:/ { skip=($2==pkg) } + /^$/ { if(skip){skip=0; next} } + !skip { print } + ' "$STATUS_FILE" > "${STATUS_FILE}.tmp" + mv "${STATUS_FILE}.tmp" "$STATUS_FILE" +fi + +cat >> "$STATUS_FILE" << STEOF + +Package: $PKG +Version: $PKG_VER +Depends: luci-compat, luci-base, curl, openssl-util +Status: install user installed +Architecture: all +Conffiles: + /etc/config/openclaw 0 +Installed-Time: $INSTALL_TIME +STEOF + +echo "已注册到 opkg (iStore 可管理)" + +# 执行 uci-defaults +if [ -f /etc/uci-defaults/99-openclaw ]; then + echo "执行初始化脚本..." + ( . /etc/uci-defaults/99-openclaw ) && rm -f /etc/uci-defaults/99-openclaw +fi + +# 清除 LuCI 缓存 +rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* 2>/dev/null + +echo "" +echo "✅ 安装完成!" +echo "" +echo "后续步骤:" +echo " 1. 运行 openclaw-env setup — 下载 Node.js 并安装 OpenClaw" +echo " 2. 访问 LuCI → 服务 → OpenClaw 进行配置" +echo " 3. 或执行 /etc/init.d/openclaw enable && /etc/init.d/openclaw start" +echo "" + +exit 0 +__ARCHIVE_BELOW__ +INSTALLER_EOF +} + +# 构建 +echo "" +echo "[1/4] 安装文件到暂存区..." +install_files "$STAGING/payload" + +echo "[2/4] 生成文件列表..." +# 生成安装文件列表 (供 opkg 卸载时使用) +FILE_LIST=$(cd "$STAGING/payload" && find . -type f | sed 's|^\./|/|' | sort) +echo " 共 $(echo "$FILE_LIST" | wc -l | tr -d ' ') 个文件" + +echo "[3/4] 创建安装器..." +create_installer + +# 替换安装器中的占位符 +sed -i "s|__PKG_VERSION__|${PKG_VERSION}|g" "$STAGING/install.sh" +# 替换文件列表占位符 — 使用临时文件拼接避免 sed/awk 多行问题 +{ + sed '/__FILE_LIST__/,$d' "$STAGING/install.sh" + echo "$FILE_LIST" + sed '1,/__FILE_LIST__/d' "$STAGING/install.sh" +} > "$STAGING/install_final.sh" +mv "$STAGING/install_final.sh" "$STAGING/install.sh" + +echo "[4/4] 打包..." +mkdir -p "$OUT_DIR" + +# 创建 payload tarball +(cd "$STAGING/payload" && tar czf "$STAGING/payload.tar.gz" .) + +# 组合: installer header + payload +RUN_FILE="$OUT_DIR/${PKG_NAME}_${PKG_VERSION}.run" +cat "$STAGING/install.sh" "$STAGING/payload.tar.gz" > "$RUN_FILE" +chmod +x "$RUN_FILE" + +FILE_SIZE=$(wc -c < "$RUN_FILE" | tr -d ' ') +echo "" +echo "=== 构建完成 ===" +echo "输出文件: $RUN_FILE" +echo "文件大小: $FILE_SIZE bytes" +echo "" +echo "安装方法: sh ${PKG_NAME}_${PKG_VERSION}.run"