diff --git a/.gitea/workflows/tests.yml b/.gitea/workflows/tests.yml index 9c1a44e..8d652d2 100644 --- a/.gitea/workflows/tests.yml +++ b/.gitea/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: # Self-hosted Gitea runners are registered as internal_docker, not ubuntu-latest. runs-on: internal_docker container: - image: node:22.22.1 + image: node:22.22.3 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d058b2e..0e66ae6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,7 @@ jobs: # Self-hosted Gitea runners are registered as internal_docker, not ubuntu-latest. runs-on: internal_docker container: - image: node:22.22.1 + image: node:22.22.3 steps: - uses: actions/checkout@v4 diff --git a/bootable/linux-setup/setup-openclaw.sh b/bootable/linux-setup/setup-openclaw.sh index e9d6269..90dd49e 100644 --- a/bootable/linux-setup/setup-openclaw.sh +++ b/bootable/linux-setup/setup-openclaw.sh @@ -7,7 +7,7 @@ set -euo pipefail # ── All constants defined here (independent of any other project files) ── -NODE_VERSION="v22.22.1" +NODE_VERSION="v22.22.3" NODE_MIRROR="https://nodejs.org/dist" NODE_OFFICIAL="https://nodejs.org/dist" NPM_MIRROR="https://registry.npmjs.org" diff --git a/bootable/linux-setup/test-installation.sh b/bootable/linux-setup/test-installation.sh index b16654f..9fffc51 100755 --- a/bootable/linux-setup/test-installation.sh +++ b/bootable/linux-setup/test-installation.sh @@ -59,8 +59,8 @@ if [ -x "$NODE_BIN" ]; then NODE_VERSION=$("$NODE_BIN" --version 2>/dev/null || echo "") echo -e "[OK] Node.js ${GREEN}$NODE_VERSION${NC}" - if [ "$NODE_VERSION" != "v22.22.1" ]; then - warn "Node.js version" "Expected v22.22.1, found $NODE_VERSION" + if [ "$NODE_VERSION" != "v22.22.3" ]; then + warn "Node.js version" "Expected v22.22.3, found $NODE_VERSION" fi else echo -e "${RED}[!!] Node.js is missing or will not run${NC}" diff --git a/install/install.ps1 b/install/install.ps1 index aaf1e29..213d44d 100644 --- a/install/install.ps1 +++ b/install/install.ps1 @@ -22,7 +22,7 @@ $RUNTIME_DIR = "$UCLAW_DIR\runtime" $CORE_DIR = "$UCLAW_DIR\core" $DATA_DIR = "$UCLAW_DIR\data" $CONFIG_PATH = "$DATA_DIR\.openclaw\openclaw.json" -$NODE_VERSION = "v22.22.1" +$NODE_VERSION = "v22.22.3" $MIRROR = "https://registry.npmjs.org" $NODE_MIRROR = "https://nodejs.org/dist" $OPENCLAW_VERSION = "2026.7.1-2" diff --git a/install/install.sh b/install/install.sh index a7edcae..402f8a3 100644 --- a/install/install.sh +++ b/install/install.sh @@ -25,7 +25,7 @@ RUNTIME_DIR="$UCLAW_DIR/runtime" CORE_DIR="$UCLAW_DIR/core" DATA_DIR="$UCLAW_DIR/data" CONFIG_PATH="$DATA_DIR/.openclaw/openclaw.json" -NODE_VERSION="v22.22.1" +NODE_VERSION="v22.22.3" MIRROR="https://registry.npmjs.org" NODE_MIRROR="https://nodejs.org/dist" OPENCLAW_VERSION="2026.7.1-2" diff --git a/portable/advanced/Mac-Install.command b/portable/advanced/Mac-Install.command index 964ef81..54637a0 100755 --- a/portable/advanced/Mac-Install.command +++ b/portable/advanced/Mac-Install.command @@ -18,7 +18,7 @@ NC='\033[0m' BOLD='\033[1m' DIM='\033[2m' -NODE_VER="$(tr -d "[:space:]" < "$UCLAW_DIR/NODE_VERSION" 2>/dev/null || tr -d "[:space:]" < "$UCLAW_DIR/../NODE_VERSION" 2>/dev/null || echo v22.22.1)" +NODE_VER="$(tr -d "[:space:]" < "$UCLAW_DIR/NODE_VERSION" 2>/dev/null || tr -d "[:space:]" < "$UCLAW_DIR/../NODE_VERSION" 2>/dev/null || echo v22.22.3)" MIRROR="https://registry.npmjs.org" NODE_MIRROR="https://nodejs.org/dist" diff --git a/portable/advanced/Windows-Install.bat b/portable/advanced/Windows-Install.bat index 0f55d61..2ad509b 100644 --- a/portable/advanced/Windows-Install.bat +++ b/portable/advanced/Windows-Install.bat @@ -15,7 +15,7 @@ set "APP_DIR=%UCLAW_DIR%app" set "INSTALL_TARGET=%USERPROFILE%\.uclaw" set "MIRROR=https://registry.npmjs.org" set "NODE_MIRROR=https://nodejs.org/dist" -set "NODE_VER=v22.22.1" +set "NODE_VER=v22.22.3" REM ---- Step 1: Check environment ---- echo [1/4] Checking diff --git a/portable/advanced/setup.bat b/portable/advanced/setup.bat index 55fc85a..d65454a 100644 --- a/portable/advanced/setup.bat +++ b/portable/advanced/setup.bat @@ -9,7 +9,7 @@ set "CORE_DIR=%APP_DIR%\core" set "RUNTIME_DIR=%APP_DIR%\runtime" set "MIRROR=https://registry.npmjs.org" set "NODE_MIRROR=https://nodejs.org/dist" -set "NODE_VERSION=v22.22.1" +set "NODE_VERSION=v22.22.3" set "ALL_PLATFORMS=false" if "%~1"=="--all-platforms" set "ALL_PLATFORMS=true" diff --git a/portable/advanced/setup.ps1 b/portable/advanced/setup.ps1 index d4c48b9..901e9cb 100644 --- a/portable/advanced/setup.ps1 +++ b/portable/advanced/setup.ps1 @@ -11,7 +11,7 @@ $runtimeDir = Join-Path $appDir "runtime" $mirror = "https://registry.npmjs.org" $nodeMirror = "https://nodejs.org/dist" -$nodeVersion = "v22.22.1" +$nodeVersion = "v22.22.3" function Write-Step { param( diff --git a/portable/advanced/setup.sh b/portable/advanced/setup.sh index 3af17c8..75c7583 100755 --- a/portable/advanced/setup.sh +++ b/portable/advanced/setup.sh @@ -13,7 +13,7 @@ CORE_DIR="$APP_DIR/core" RUNTIME_DIR="$APP_DIR/runtime" MIRROR="https://registry.npmjs.org" NODE_MIRROR="https://nodejs.org/dist" -NODE_VERSION="$(tr -d "[:space:]" < "$SCRIPT_DIR/NODE_VERSION" 2>/dev/null || tr -d "[:space:]" < "$SCRIPT_DIR/../NODE_VERSION" 2>/dev/null || echo v22.22.1)" +NODE_VERSION="$(tr -d "[:space:]" < "$SCRIPT_DIR/NODE_VERSION" 2>/dev/null || tr -d "[:space:]" < "$SCRIPT_DIR/../NODE_VERSION" 2>/dev/null || echo v22.22.3)" ALL_PLATFORMS=false [ "$1" = "--all-platforms" ] && ALL_PLATFORMS=true diff --git a/tests/origin.test.mjs b/tests/origin.test.mjs index 4232997..e99c438 100644 --- a/tests/origin.test.mjs +++ b/tests/origin.test.mjs @@ -8,6 +8,8 @@ const repoRoot = fileURLToPath(new URL('..', import.meta.url)); const origin = JSON.parse(readFileSync(join(repoRoot, 'origin.json'), 'utf8')); const SKIPPED_DIRS = new Set(['.git', 'node_modules', 'dist', '.download-cache', 'tests']); +// portable/app/ is gitignored — setup downloads Node/OpenClaw there for local runs. +const SKIPPED_PATH_PREFIXES = ['portable/app/']; // Lockfiles are full of third-party funding and repository links. They say // nothing about where *this* build fetches from. const SKIPPED_FILES = new Set(['package-lock.json']); @@ -17,6 +19,8 @@ function* walk(dir) { for (const entry of readdirSync(dir)) { if (SKIPPED_DIRS.has(entry)) continue; const full = join(dir, entry); + const rel = relative(repoRoot, full); + if (rel === 'portable/app' || SKIPPED_PATH_PREFIXES.some((p) => rel.startsWith(p))) continue; if (statSync(full).isDirectory()) yield* walk(full); else yield full; } diff --git a/u-claw-app/resources/Config.html b/u-claw-app/resources/Config.html index dc00b6d..5c784f7 100644 --- a/u-claw-app/resources/Config.html +++ b/u-claw-app/resources/Config.html @@ -59,7 +59,9 @@ h1 .lobster { color: #ff6b35; } } .form-group input, input[type="text"], -input[type="password"] { +input[type="password"], +.form-group select, +select { display: block; width: 100%; min-width: 0; @@ -74,6 +76,20 @@ input[type="password"] { outline: none; transition: border-color 0.2s; } +.form-group select, +select { + padding-right: 36px; + cursor: pointer; + appearance: none; + -webkit-appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23888' d='M1 1l5 5 5-5'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 14px center; +} +.form-group select:focus, +select:focus { border-color: #ff6b35; } +.form-group select option, +select option { background: #222; color: #fff; } input:focus { border-color: #ff6b35; } .input-wrap { position: relative; display: block; width: 100%; min-width: 0; } .input-wrap input { padding-right: 70px; } @@ -114,6 +130,37 @@ input:focus { border-color: #ff6b35; } .btn-secondary:hover { background: #444; } .btn-row { display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end; } +/* Key verified: model picker + continue on one row */ +.key-actions { + display: flex; + align-items: flex-end; + gap: 12px; + margin-top: 16px; + margin-bottom: 4px; +} +.key-actions .model-picker { + flex: 1; + min-width: 0; + margin-bottom: 0; +} +.key-actions .model-picker label { + margin-bottom: 6px; + font-size: 0.85em; + color: #aaa; +} +.key-actions .btn-primary { + flex-shrink: 0; + min-width: 128px; + min-height: 46px; + padding: 12px 22px; + margin-left: auto; +} +.key-actions.has-model .btn-primary { margin-left: 0; } +@media (max-width: 520px) { + .key-actions { flex-direction: column; align-items: stretch; } + .key-actions .btn-primary { margin-left: 0; width: 100%; } +} + /* Result */ .result { text-align: center; padding: 40px 20px; } .result .icon { font-size: 3em; margin-bottom: 12px; } @@ -126,15 +173,29 @@ input:focus { border-color: #ff6b35; } .toast.show { opacity: 1; transform: translateY(0); } .toast.error { background: #f44336; } -/* Channel form */ +/* Channel form — open state must scroll (Telegram pairing steps are tall) */ .channel-card { transition: all 0.2s; } .channel-card.selected { border-color: #ff6b35; background: rgba(255,107,53,0.06); } -.channel-form { padding-top: 0; margin-top: 10px; border-top: 1px solid #333; max-height: 0; overflow: hidden; transition: max-height 0.3s ease, padding 0.3s ease; } -.channel-form.open { max-height: 300px; padding-top: 12px; } +.channel-form { padding-top: 0; margin-top: 10px; border-top: 1px solid #333; max-height: 0; overflow: hidden; transition: max-height 0.35s ease, padding 0.35s ease; } +.channel-form.open { + max-height: min(72vh, 560px); + overflow-x: hidden; + overflow-y: auto; + padding-top: 12px; + padding-bottom: 4px; + -webkit-overflow-scrolling: touch; + scrollbar-gutter: stable; +} +.channel-form.open::-webkit-scrollbar { width: 8px; } +.channel-form.open::-webkit-scrollbar-thumb { background: #444; border-radius: 4px; } +.channel-form.open::-webkit-scrollbar-thumb:hover { background: #555; } +/* Telegram needs the full row when expanded */ +.channel-card.channel-expanded { grid-column: 1 / -1; } .channel-form .form-group { margin-bottom: 10px; } .channel-form label { font-size: 0.82em; color: #aaa; margin-bottom: 4px; } .channel-form input { font-size: 0.88em; padding: 9px 12px; } .channel-form .hint { font-size: 0.75em; margin-top: 4px; } +.tg-steps code { background: #2a2a2a; padding: 1px 5px; border-radius: 4px; color: #ffb84d; font-size: 0.95em; } /* Status bar */ .status-bar { @@ -203,12 +264,11 @@ body[data-tier="standard"] [data-tier-min="expert"] { display: none !important; -
- -After saving, connect your Telegram account:
+/start.