From 7a6ffa3c42037ad44e020fd860af20dda76a0174 Mon Sep 17 00:00:00 2001 From: LetItBe12345 Date: Sun, 26 Jul 2026 22:00:53 +0800 Subject: [PATCH] ci: split quality integration and release candidate workflows --- .github/workflows/ci.yml | 147 +++++----------- .github/workflows/release.yml | 245 ++++++++++++++++++-------- README.md | 99 ++++++++++- docs/assets/omp-desktop-workspace.png | Bin 0 -> 110335 bytes docs/releasing.md | 23 ++- scripts/ci-linux-display-smoke.sh | 39 ++-- scripts/electron-smoke.mjs | 26 +-- src/main/index.ts | 1 + 8 files changed, 368 insertions(+), 212 deletions(-) create mode 100644 docs/assets/omp-desktop-workspace.png diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a77874..8fe2abe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,9 +3,7 @@ name: CI on: pull_request: push: - branches: - - main - workflow_dispatch: + branches: [main] permissions: contents: read @@ -16,7 +14,7 @@ concurrency: jobs: quality: - name: Quality and build + name: Quality runs-on: ubuntu-24.04 timeout-minutes: 15 steps: @@ -24,35 +22,28 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - name: Install pnpm uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: .node-version cache: pnpm cache-dependency-path: pnpm-lock.yaml - - name: Install dependencies run: pnpm install --frozen-lockfile - - - name: Check source - run: pnpm check - - - name: Run fake RPC smoke + - name: Typecheck + run: pnpm typecheck + - name: Lint + run: pnpm lint + - name: Format check + run: pnpm format:check + - name: Test + run: pnpm test + - name: Fake RPC smoke run: OMP_RPC_FAKE=1 node scripts/rpc-smoke.mjs - - - name: Download and verify OMP Runtime - run: pnpm runtime:download - - - name: Run real OMP RPC smoke without model API - run: OMP_RPC_TEST_CONFIG=1 node scripts/rpc-smoke.mjs - - - name: Build application + - name: Build run: pnpm build - - name: Check production output shell: bash run: | @@ -66,8 +57,9 @@ jobs: exit 1 fi - linux-package: - name: Linux x64 packages + linux-integration: + name: Linux integration and packages + if: github.event_name == 'push' && github.ref == 'refs/heads/main' needs: quality runs-on: ubuntu-24.04 timeout-minutes: 30 @@ -86,37 +78,36 @@ jobs: cache-dependency-path: pnpm-lock.yaml - name: Install dependencies run: pnpm install --frozen-lockfile - - name: Download Runtime and build packages - run: pnpm runtime:download && pnpm package:linux && pnpm package:check + - name: Download and verify OMP Runtime + run: pnpm runtime:download && pnpm runtime:check + - name: Real RPC smoke + run: OMP_RPC_TEST_CONFIG=1 node scripts/rpc-smoke.mjs + - name: Build x64 packages + run: pnpm package:linux && pnpm package:check - name: Inspect package metadata shell: bash run: | set -euo pipefail deb="$(find dist -maxdepth 1 -name '*.deb' -print -quit)" dpkg-deb --info "$deb" - dpkg-deb --contents "$deb" | tee dist/deb-contents.txt - if rg -n 'tests/|tmp/|omp-linux-arm64|\.map$' dist/deb-contents.txt; then - echo '安装包包含测试、临时、arm64 或 source map 文件' >&2 - exit 1 - fi test "$(dpkg-deb -f "$deb" Architecture)" = amd64 test "$(dpkg-deb -f "$deb" Package)" = omp-desktop - name: Upload packages uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: linux-x64-packages + name: main-linux-x64-${{ github.sha }} path: | dist/*.AppImage dist/*.deb dist/*.sha256 dist/build-metrics.json - dist/deb-contents.txt if-no-files-found: error retention-days: 7 linux-display-smoke: - name: Linux ${{ matrix.ubuntu }} / ${{ matrix.arch }} / ${{ matrix.display }} - needs: quality + name: Ubuntu ${{ matrix.ubuntu }} x64 ${{ matrix.display }} smoke + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: linux-integration runs-on: ${{ matrix.runner }} timeout-minutes: 20 strategy: @@ -125,89 +116,47 @@ jobs: include: - runner: ubuntu-22.04 ubuntu: '22.04' - arch: x64 display: x11 - - runner: ubuntu-22.04 - ubuntu: '22.04' - arch: x64 - display: wayland - runner: ubuntu-24.04 ubuntu: '24.04' - arch: x64 - display: x11 - - runner: ubuntu-24.04 - ubuntu: '24.04' - arch: x64 - display: wayland - - runner: ubuntu-22.04-arm - ubuntu: '22.04' - arch: arm64 - display: x11 - - runner: ubuntu-22.04-arm - ubuntu: '22.04' - arch: arm64 - display: wayland - - runner: ubuntu-24.04-arm - ubuntu: '24.04' - arch: arm64 - display: x11 - - runner: ubuntu-24.04-arm - ubuntu: '24.04' - arch: arm64 display: wayland steps: - - name: Checkout + - name: Checkout smoke scripts uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - - name: Install pnpm - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - + sparse-checkout: | + scripts + .node-version - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: .node-version - cache: pnpm - cache-dependency-path: pnpm-lock.yaml - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build application - run: pnpm build - - - name: Configure Electron sandbox - shell: bash - run: | - set -euo pipefail - electron_dir="$(dirname "$(node -p "require('electron')")")" - sandbox_path="$electron_dir/chrome-sandbox" - test -f "$sandbox_path" - sudo chown root:root "$sandbox_path" - sudo chmod 4755 "$sandbox_path" - stat -c '%U:%G %a %n' "$sandbox_path" - - - name: Install X11 test dependencies - if: matrix.display == 'x11' - run: | - sudo apt-get update - sudo apt-get install --yes --no-install-recommends dbus-x11 xauth xvfb - - - name: Install Wayland test dependencies - if: matrix.display == 'wayland' + - name: Download main packages + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: main-linux-x64-${{ github.sha }} + path: candidate + - name: Verify candidate checksums + working-directory: candidate + run: sha256sum -c *.deb.sha256 + - name: Install candidate deb + run: sudo apt-get update && sudo apt-get install --yes ./candidate/*.deb + - name: Install display dependencies run: | sudo apt-get update - sudo apt-get install --yes --no-install-recommends dbus-x11 weston - - - name: Run display smoke - run: dbus-run-session -- bash scripts/ci-linux-display-smoke.sh "${{ matrix.display }}" - + if [[ '${{ matrix.display }}' == x11 ]]; then + sudo apt-get install --yes --no-install-recommends dbus-x11 xauth xvfb + else + sudo apt-get install --yes --no-install-recommends dbus-x11 weston + fi + - name: Run packaged display smoke + run: dbus-run-session -- bash scripts/ci-linux-display-smoke.sh '${{ matrix.display }}' '/opt/OMP Desktop/omp-desktop' - name: Upload smoke diagnostics if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: linux-${{ matrix.ubuntu }}-${{ matrix.arch }}-${{ matrix.display }} + name: main-${{ matrix.ubuntu }}-${{ matrix.display }}-smoke path: | ${{ runner.temp }}/omp-ci/** tests/artifacts/*.png diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2f52350..2b64f9e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: release_version: - description: Stable SemVer without v, for example 0.1.0 + description: Stable SemVer without v, for example 0.1.1 required: true type: string @@ -16,31 +16,20 @@ concurrency: cancel-in-progress: false jobs: - gpu-acceptance: - name: RTX 3090 Wayland acceptance - runs-on: [self-hosted, linux, x64] - timeout-minutes: 20 + build-candidate: + name: Build release candidate + runs-on: ubuntu-24.04 + timeout-minutes: 35 steps: - name: Validate version shell: bash run: | set -euo pipefail - if [[ ! '${{ inputs.release_version }}' =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo 'release_version 必须是稳定 SemVer X.Y.Z' >&2 - exit 1 - fi + [[ '${{ inputs.release_version }}' =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] - name: Checkout requested commit uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - name: Check native Wayland and RTX 3090 - shell: bash - run: | - set -euo pipefail - test "${XDG_SESSION_TYPE:-}" = wayland - test -n "${WAYLAND_DISPLAY:-}" - nvidia-smi --query-gpu=name --format=csv,noheader | tee gpu-name.txt - grep -Eiq 'RTX 3090' gpu-name.txt - name: Install pnpm uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - name: Install Node.js @@ -49,35 +38,129 @@ jobs: node-version-file: .node-version cache: pnpm cache-dependency-path: pnpm-lock.yaml - - name: Install, verify Runtime and build + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Set candidate version and build once run: | - set -euo pipefail - pnpm install --frozen-lockfile - runtime_url="$(node -p "JSON.parse(require('fs').readFileSync('runtime/manifest.json', 'utf8')).url")" - curl --fail --location --retry 3 --retry-delay 2 "$runtime_url" -o runtime/omp - chmod 0755 runtime/omp + pnpm pkg set version='${{ inputs.release_version }}' + pnpm runtime:download pnpm runtime:check - pnpm check - pnpm build - - name: Run hardware GPU smoke + pnpm package:linux + pnpm package:check + - name: Check candidate metadata shell: bash run: | set -euo pipefail - system_sandbox=/usr/share/typora/chrome-sandbox - test "$(stat -c '%U:%G %a' "$system_sandbox")" = 'root:root 4755' - electron_binary="$(node -p "require('electron')")" - electron_sandbox="$(dirname "$electron_binary")/chrome-sandbox" - rm -f "$electron_sandbox" - ln -s "$system_sandbox" "$electron_sandbox" - mkdir -p tests/artifacts - OMP_SMOKE_SCREENSHOT="$PWD/tests/artifacts/gpu-smoke.png" \ - OMP_GPU_ACCEPTANCE_OUTPUT="$PWD/tests/artifacts/gpu-info.json" \ - pnpm smoke - if grep -En '"(gpu_compositing|webgl|webgl2)": "(disabled|unavailable|software)' tests/artifacts/gpu-info.json; then - echo 'Electron 没有使用预期的硬件加速' >&2 - exit 1 + deb="$(find dist -maxdepth 1 -name '*.deb' -print -quit)" + test "$(dpkg-deb -f "$deb" Version)" = '${{ inputs.release_version }}' + test "$(dpkg-deb -f "$deb" Architecture)" = amd64 + test "$(dpkg-deb -f "$deb" Package)" = omp-desktop + - name: Upload the only release candidate + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: release-candidate-${{ github.sha }}-${{ inputs.release_version }} + path: | + dist/*.AppImage + dist/*.deb + dist/*.sha256 + dist/build-metrics.json + if-no-files-found: error + retention-days: 30 + + hosted-full-matrix: + name: Ubuntu ${{ matrix.ubuntu }} x64 ${{ matrix.display }} candidate smoke + needs: build-candidate + runs-on: ${{ matrix.runner }} + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-22.04 + ubuntu: '22.04' + display: x11 + - runner: ubuntu-22.04 + ubuntu: '22.04' + display: wayland + - runner: ubuntu-24.04 + ubuntu: '24.04' + display: x11 + - runner: ubuntu-24.04 + ubuntu: '24.04' + display: wayland + steps: + - name: Checkout smoke scripts + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + sparse-checkout: | + scripts + .node-version + - name: Install Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version-file: .node-version + - name: Download the release candidate + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: release-candidate-${{ github.sha }}-${{ inputs.release_version }} + path: candidate + - name: Verify candidate checksums + working-directory: candidate + run: sha256sum -c *.deb.sha256 + - name: Install candidate deb + run: sudo apt-get update && sudo apt-get install --yes ./candidate/*.deb + - name: Install display dependencies + run: | + sudo apt-get update + if [[ '${{ matrix.display }}' == x11 ]]; then + sudo apt-get install --yes --no-install-recommends dbus-x11 xauth xvfb + else + sudo apt-get install --yes --no-install-recommends dbus-x11 weston fi - - name: Verify manual acceptance record + - name: Run candidate display smoke + run: dbus-run-session -- bash scripts/ci-linux-display-smoke.sh '${{ matrix.display }}' '/opt/OMP Desktop/omp-desktop' + - name: Upload display diagnostics + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: release-${{ matrix.ubuntu }}-${{ matrix.display }}-smoke + path: | + ${{ runner.temp }}/omp-ci/** + tests/artifacts/*.png + if-no-files-found: warn + retention-days: 30 + + gpu-acceptance: + name: RTX 3090 Wayland candidate acceptance + needs: [build-candidate, hosted-full-matrix] + runs-on: [self-hosted, Linux, X64, rtx3090, wayland] + timeout-minutes: 25 + steps: + - name: Validate native Wayland and RTX 3090 + shell: bash + run: | + set -euo pipefail + test "${XDG_SESSION_TYPE:-}" = wayland + test -n "${WAYLAND_DISPLAY:-}" + nvidia-smi --query-gpu=name --format=csv,noheader | tee gpu-name.txt + grep -Eiq 'RTX 3090' gpu-name.txt + - name: Checkout smoke and acceptance scripts + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + sparse-checkout: | + scripts + .node-version + - name: Download the release candidate + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: release-candidate-${{ github.sha }}-${{ inputs.release_version }} + path: candidate + - name: Verify candidate checksums + working-directory: candidate + run: sha256sum -c *.AppImage.sha256 + - name: Verify existing manual acceptance record shell: bash run: | set -euo pipefail @@ -85,64 +168,74 @@ jobs: acceptance_file="$state_root/omp-desktop/release-acceptance/${GITHUB_SHA}.json" node scripts/gpu-acceptance.mjs verify "$acceptance_file" \ --commit "$GITHUB_SHA" --version '${{ inputs.release_version }}' + mkdir -p tests/artifacts cp "$acceptance_file" tests/artifacts/gpu-acceptance.json + - name: Run the candidate AppImage on real GPU + shell: bash + run: | + set -euo pipefail + appimage="$(find candidate -maxdepth 1 -name '*.AppImage' -print -quit)" + chmod +x "$appimage" + mkdir -p tests/artifacts + APPIMAGE_EXTRACT_AND_RUN=1 \ + OMP_DISPLAY_SERVER=wayland \ + OMP_SMOKE_EXECUTABLE="$PWD/$appimage" \ + OMP_SMOKE_SCREENSHOT="$PWD/tests/artifacts/gpu-smoke.png" \ + OMP_GPU_ACCEPTANCE_OUTPUT="$PWD/tests/artifacts/gpu-info.json" \ + node scripts/electron-smoke.mjs + node --input-type=commonjs - <<'NODE' + const fs = require('node:fs') + const data = JSON.parse(fs.readFileSync('tests/artifacts/gpu-info.json', 'utf8')) + const status = data.featureStatus || {} + for (const key of ['gpu_compositing', 'webgl', 'webgl2']) { + if (!status[key] || /disabled|unavailable|software/i.test(status[key])) { + throw new Error(`GPU feature ${key} 未通过: ${status[key]}`) + } + } + NODE - name: Upload GPU evidence + if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: gpu-acceptance-${{ github.sha }} - path: tests/artifacts/* + path: | + tests/artifacts/* + gpu-name.txt if-no-files-found: error retention-days: 90 - build-release: - name: Build draft release - needs: gpu-acceptance + create-draft-release: + name: Create draft release + needs: [build-candidate, hosted-full-matrix, gpu-acceptance] runs-on: ubuntu-24.04 - timeout-minutes: 35 + timeout-minutes: 15 steps: - - name: Checkout accepted commit + - name: Checkout release metadata uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - name: Install pnpm - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - - name: Install Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - name: Download the same release candidate + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - node-version-file: .node-version - cache: pnpm - cache-dependency-path: pnpm-lock.yaml - - name: Build release packages - shell: bash - run: | - set -euo pipefail - pnpm install --frozen-lockfile - pnpm pkg set version='${{ inputs.release_version }}' - runtime_url="$(node -p "JSON.parse(require('fs').readFileSync('runtime/manifest.json', 'utf8')).url")" - curl --fail --location --retry 3 --retry-delay 2 "$runtime_url" -o runtime/omp - chmod 0755 runtime/omp - pnpm runtime:check - pnpm package:linux - pnpm package:check - deb="$(find dist -maxdepth 1 -name '*.deb' -print -quit)" - test "$(dpkg-deb -f "$deb" Version)" = '${{ inputs.release_version }}' - test "$(dpkg-deb -f "$deb" Architecture)" = amd64 + name: release-candidate-${{ github.sha }}-${{ inputs.release_version }} + path: dist + - name: Download GPU evidence + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: gpu-acceptance-${{ github.sha }} + path: gpu-evidence - name: Write release notes shell: bash run: | set -euo pipefail - appimage="$(basename "$(find dist -maxdepth 1 -name '*.AppImage' -print -quit)")" - deb="$(basename "$(find dist -maxdepth 1 -name '*.deb' -print -quit)")" printf '%s\n' \ '# OMP Desktop v${{ inputs.release_version }}' \ '' \ - '- 支持:Ubuntu 22.04、24.04 x64' \ - '- Bundled OMP:v17.1.0' \ - "- AppImage:$appimage" \ - "- Debian:$deb" \ - '- GPU 验收:RTX 3090、原生 Wayland,绑定 commit ${{ github.sha }}' \ + '- x64:Ubuntu 22.04/24.04,X11/Wayland Hosted smoke' \ + '- RTX 3090 原生 Wayland 真机验收' \ + '- AppImage 和 deb 从同一个 Release Candidate 构建,后续未重新打包' \ '' \ - '发布前请人工检查 SHA-256、已知问题和 GPU artifact。' > release-notes.md + '请人工检查 Draft Release 的文件、SHA-256、截图和 GPU artifact,再点击 Publish。' > release-notes.md - name: Create or update Draft Release env: GH_TOKEN: ${{ github.token }} diff --git a/README.md b/README.md index 042876a..f4fce0f 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,105 @@ # OMP Desktop -OMP Desktop 是 OMP 的 Linux 桌面客户端。首个发布版只提供 Ubuntu 22.04/24.04、x86-64 的 AppImage 和 `.deb`,内置 OMP `v17.1.0`。 +面向本地项目的 OMP Agent 桌面客户端。把 Workspace、会话、文件和 Agent 任务放在同一个 Ubuntu 原生窗口中。 -## 使用 +**[下载最新版本](https://github.com/LetItBe12345/omp_app/releases/latest)** · [安装说明](docs/ubuntu-installation.md) · [提交问题](https://github.com/LetItBe12345/omp_app/issues) -1. 从 GitHub Release 下载 `omp-desktop-*-linux-x64.AppImage` 或 `.deb`,按 [Ubuntu 安装说明](docs/ubuntu-installation.md) 校验 SHA-256 并安装。 -2. 第一次没有 Provider 凭据时,在终端运行 `omp-desktop --setup-provider`。这会启动内置 OMP 的交互终端;按 OMP 的提示完成 Provider 登录,然后退出。Desktop 不读取或保存 Token。 -3. 正常运行 `omp-desktop`,选择 Workspace,新建 Session,在模型选择器中选择模型并发送 Prompt。后续新增 Provider 或重新登录在 GUI 中完成。 -4. 图形驱动黑屏时可从终端运行 `omp-desktop --disable-gpu`;该参数只对本次启动生效。 -5. 卸载 `.deb` 使用 `sudo apt remove omp-desktop`。卸载不会删除 Workspace、Session、Runtime 设置或日志;重新安装后会继续使用这些数据。 +[![Release](https://img.shields.io/github/v/release/LetItBe12345/omp_app?label=release)](https://github.com/LetItBe12345/omp_app/releases/latest) +[![CI](https://github.com/LetItBe12345/omp_app/actions/workflows/ci.yml/badge.svg)](https://github.com/LetItBe12345/omp_app/actions/workflows/ci.yml) +[![Ubuntu](https://img.shields.io/badge/Ubuntu-22.04%20%7C%2024.04-E95420)](docs/ubuntu-installation.md) +[![License](https://img.shields.io/badge/license-MIT-2f2f2f)](LICENSE) -安装包、Runtime 和详细验收步骤见 [发布验收](docs/release-acceptance.md);维护者发布流程见 [发布流程](docs/releasing.md)。 +

+ OMP Desktop 在 Ubuntu Wayland 中管理 Workspace、文件树和 Agent 会话 +

+ +

Ubuntu 24.04 · Wayland · 三栏 Workspace 工作界面

+ +OMP Desktop 不是一个新的 IDE。它是 OMP 的图形工作台,让你在不离开项目上下文的情况下管理会话、选择文件、发送任务,并查看 Agent 的流式输出、Thinking、Tool Call 和权限请求。 + +## 当前能力 + +- 管理多个本地 Workspace,以及各 Workspace 下的会话。 +- 在独立文件栏中浏览和搜索当前项目,将文件、目录或历史会话加入上下文。 +- 查看流式回答、Thinking、工具执行状态和 Permission 请求。 +- 选择模型、Thinking 等级和执行权限,支持 Stop 与逐条 Follow-up。 +- 自动恢复上次 Workspace、会话、草稿和 Runtime 设置。 +- 为 OMP Runtime 单独配置直连、自动代理或手动 HTTP 代理,不要求开启系统全局代理。 +- 内置固定版本的 OMP Runtime,安装后不再下载应用组件。 + +## 安装 + +当前正式支持 Ubuntu 22.04 LTS、24.04 LTS x86-64。 + +从 [GitHub Releases](https://github.com/LetItBe12345/omp_app/releases/latest) 下载 `.deb` 和对应的 `.sha256` 文件: + +```sh +sha256sum -c omp-desktop-0.1.0-linux-x64.deb.sha256 +sudo apt install ./omp-desktop-0.1.0-linux-x64.deb +``` + +也可以下载 AppImage 直接运行。完整步骤、FUSE 要求和卸载方式见 [Ubuntu 安装说明](docs/ubuntu-installation.md)。 + +## 首次使用 + +第一次使用前,在终端配置 OMP Provider: + +```sh +omp-desktop --setup-provider +``` + +这条命令会在当前终端启动应用内置的 OMP 配置界面。按提示完成 Provider 登录后退出,再从桌面启动器打开 OMP Desktop。 + +Desktop 不读取或保存 Provider Token。凭据由 OMP 自己管理。 + +进入应用后: + +1. 点击 Workspace 旁的 `+`,选择本地项目目录。 +2. 新建或打开一个会话。 +3. 等待底部 Runtime 状态变为就绪。 +4. 选择模型、Thinking 等级和权限模式,然后发送任务。 +5. 通过文件树或输入框的 `@` 引用补充项目上下文。 + +遇到显卡驱动导致的黑屏时,可以用下面的命令进行临时诊断: + +```sh +omp-desktop --disable-gpu +``` + +该参数只对本次启动生效,不是默认运行方式。 + +## 产品边界 + +当前版本聚焦本地 Agent 工作流,不提供应用内代码编辑器、Git Diff/Review、集成终端、多窗口或插件市场。命令和文件操作由本地 OMP Runtime 执行,并受当前权限模式控制。 + +`v0.1.0` 已在 NVIDIA RTX 3090 原生 Wayland 环境完成硬件验收。Intel、AMD 和 X11 真实硬件环境尚未纳入本次正式验收范围。 ## 开发 +需要 Node.js 24 和 pnpm 11: + ```sh pnpm install pnpm runtime:download pnpm dev +``` + +提交前运行: + +```sh pnpm check +pnpm build ``` -`runtime/omp` 不提交到 Git。它由 `runtime/manifest.json` 固定的 URL 和 SHA-256 下载。生产构建使用 `pnpm package:linux`,只在 Linux x64 上生成 AppImage 和 `.deb`。 +`runtime/omp` 不提交到 Git。版本、下载地址和 SHA-256 固定在 `runtime/manifest.json`。Linux x64 打包命令: + +```sh +pnpm package:linux +pnpm package:check +``` + +架构和 RPC 说明见 [Desktop 架构](docs/desktop-architecture.md) 与 [OMP RPC](docs/OMP_RPC.md)。发布验收和维护者流程见 [发布验收](docs/release-acceptance.md) 与 [发布流程](docs/releasing.md)。 + +## License + +[MIT](LICENSE) diff --git a/docs/assets/omp-desktop-workspace.png b/docs/assets/omp-desktop-workspace.png new file mode 100644 index 0000000000000000000000000000000000000000..2cb3f7e6c283eecf246bcbca6371fb4cfec4d047 GIT binary patch literal 110335 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

V_g~k$Yr5Q&aKHik zPJ!QbG63xa$3?&ysCcpM-Tw}9#@Qc@rNbjy8wW)MT6%^qf89~IV+YhMkh~;e&2E*+ z9L{x(fw2E&3^&T&N7UQokyyvOaHuuoDskL>^c@ZV)<+l0p_T9T^jxoyVRm`mu zpZ{A1n<{p-=bppQfoL$kh2@DpxCW$^l9_g+&rdZ#!xRVO!;=^!rGiY0NPr0b3t6qH zHyW}5nYaL0oalsRW%b5y)sXA|fE=p_vY!7bg^&LBlWB3eFv}&WjvP2}0QR)9RoiIY zLP}8gGca_zy1)E?mAGpdpTxGvhlwW)_7$Mf3$^C&s0c40=Qo5u_fXkDMIDD!)o8RW z4|0(J4gz~19sl-#SKUB>))?Oi+S%LWw+O=YrLt{&w0)=9_xp=!^!J`yF-KJCPv#}8 zS<1BoESPdkhsFg4H7k@gmX>oo#^$#cjU^VHr6@op&(?UP|=I=;k@JL+KSq5n_bDprw8UbWERl@+5~_)kXz+by@B$l*w1g$%Z_V8t)iz5EBS4C!K&BVkU z@$KV^12vH=kI#E7QGWb>tp$$-bav1RiHfQEC0ljUS^ui~!?mw1%F9#szdGl1Il&RW zmQ@o&L+t($Z{A!DSr6n7UFr6A>2jIp*UKyLr=OliBR;$Vg}H=6X>KvqGI>ho#3j@HQSUG`% zlLJ79J?NeD5DiHijoF-CuukeY1L|`~RrPIte7K@$8!==0<4Riu1o;3O^8}sJUhh zsQCgPn-G{68FQc^i3c#6 ze~30&{2ut^(@mRetPb-1EMqqIy46`i{pPpbqr_wmBL{kMyF~=^(F!zL3M$cRyY(~YE{ICWFrMx*)I@B z0Z591@hsX-o4z+gO)dQt1_a1mVI(T|c`Tm$fCfN6Nrv@-CzZ)NZunL(2EXT1=R=icCm+w4j0#l;8 z%#Oq6U6nAFxX3rw{VH%bENrIwA-}u?1}C#WfyLfON-zJaGpH+ALwwy=E`HzeWOc%` zzRLcjC1Jk>(FgN7$LHsBaBP`B=CBC``lBgpB`Ky0W2(`<*~9JPhqd^90}&px&M z$@DYOsfqRcd-jZEPLNU-4L&iKl|?YEX96Fie4=m`gY_y*dWsI_uuy_=_e*ue0XB^&yr`ibHjXB__l_QNi>g%rmaaIp3VvT z09WY`+kM~g2zJd*1VI77KoZog2xFoUU7sBKc)vHeokl%?>u7}9gm46@FhWgZqiq^I?}XWDtIDZV{#XY zpzPix*a?$y6zE3W<1(|1g?~| zd7qc&9rg1-+dH-Ar&uY%!jY~AmM&e|+bDLuJ9K&zH~~S^seiCmw{u^HIa*~+>YzGg ze4p@SqL4{tRPtITVqV?rUuuevL~e5z-(1NLU+GgAL8>Di^xXr4y5!MTR|qf2VO^=& z5y!PVPPP>7oc^1g-DXoPndgUBMw+OwgIoTla+QHoRX~V68`v@M#K~!f*LMO|HporI zp-pQSu!^;v~ljGb96WGlS==WqbZ=gtbD5Apcq&f84@?jf@%s3!IdiYfshjnoV(-Pm;CmK z@{?-$O51-zexI_*TXlBuTT8Fgv$h#E&y`cg`zHi(?%v%fBo+gp;Z@yX(vq;5_+2;dkewLpc%G&r*lJ7hen{JUHBxBZ^UC z&_Ba)*z46R7V)u9`@nszGd4D6*u4Mki&M?749m4pdLM=Q49URJ(?>xRpo70P)S3MCkiRIK@2oPHxO0f9PE~rm1Um=YfMn~u-frOqtH!^TM007 z@hkoZ20{-XmZE{;nMN1SB^sq~FDclYCrnICk_NS3D1_a5_xDi`2G=e$C2Z&C4;mR! znRjk4{J#1*^3_)ca;s!yR97-ETttJ;ujv)%?uyzDZN~B5IWuWRCV`+Wf1Q03EadM1 zEwh@NQJa~G5kSVIm~uZ@(s?6x00tbwZ@w2*m^Wl;70HJDh+jp}Asi0mc7a93{kv>p zEId3sV@WWh$;Lpbk9lnG8XIq*5$r1>`r+ONz%>fveCgqZ;3)qgV^ zOx~)xz2*aauh&B9m1#7~nK1`l|7$Z%LE!ipgOGm}qr9-~0)L4z{oXsQ%6)EW2jKvR z9RF;5--@^R97si&A=E?T_mX>ofwXS-?|(hjZ9kMjWv)MNiIm+v6_iIz4gBwzfr z-fNae)uk9ZWja%SxR%PEJ-cql{i5u_sULzMcPHnj2Qe%yInNH0=3y)p98$%lSPPHW z?R-NgGHzvCjM=P8t2q&D^+yYEc^|o)ohFQizc)pJcc;Uy5 ziDzC|jb!9`?zEYhwo}pr2peiP9|(oZIqpgu#w3UPN*1FZO)ZV@5nL+0tju6$ObpNy zwVcr%QJkQe1V+OHiZ}3?MWOdUc=*23D_}(BCZKcB)n|)T8LFn*wBh5}o~8G;-VnXg zwhR#NHZHEh%`IBlc7Ax)I);YFu?8{iLm!RDn=z{m0?~)vVSDwKL$KY=?>b2jP3R|# zg=%Rz;2v5(JMGGSwjP~xm%emd3#rob@1IB4+(Ri>NsNsWXljy#iTWe306PvG*eE5{ z%p`G~IE3Ie@m!W|qzWTc@dYd}ET9Pn?^w3W-r{Vz?V|s?k;mrrG-iF}n@s;*D zEkDkn6DL2V!Tsp1t}=he#NbK!+!t=DL%ZOWm&V({8+*jV zBpc8o%u3N?u3&;?m)YMe$9t^3> zgC@vsvU488$cEi!Tr%*mm^F+lz|8@1T}5WpLWK*=oLd5Co zY_(~Fy1M!!L3=m+&eF+4eMs3i2wr+6+CbZbISP=&=?vEK)BJ+bK0G^~X;WX8>H!b$ zt&BCiW1JQ2ujQI@c{z4?0UFP-XqRBJoQrL#_t>B4Tx_cSPJN_JOj!55RN2l z#jjuA-5h|yOs{@T+H`#~q7YC~pBK{6aCF#n#?)6;z4)Bk{IhO$wjCbI4l~8Shiryj#x_|rnu?1zfVOscHdvkba@Ll*qO5FE$`HB-&-D{jy~f5d)iT(~ z7U(h$KEdp;rLd4{HI`AJ`n)upd&#b$@mNM?*W3Y0TwEOQ)E!o?zw*5lzw|TG(UIX0 z5ieh2evb&ertTugPSP(@#7(F?<@+axs&4dS&jt*Jl@M^rL`~969f&b$f4Ss{i4OPy zh0K!2fm-ppv-CzgPPpirkhs7OpP$|3VFuWQEcNI>p*QVscBNp}D31u_yHOQxo&rB_4=3_Z~fxB|KaF zdtO+p@{t)($P_{x>z81PeUf>zFWN$A;Aw0;3K9x?)d=m)M(l86WbvAWJIM)I*=;*_ zu7HKWKl5u@kb#KAKjWxooGd4%)iGI7dj96H0sB1o8oY= zx8G|saL&?d3@G4B5W>OJA*WZoj*8O?2hYHA-e-GFXDnuLO&k+*>5W)i1!a`b-8BH-k{yp@cDBPloNey1Om z4$x?!Qn>$VJ{0Zw@8Ihr4}7JkHhCvHq`J4v|MJM&B!m1LPj>{x1dc8EVSn+%ZQKKa z)5#a&P^y07-Dc*2?hgT@FJ3q`+@Kk~GTJ7s<V`6Z~m;mEe%O-Y0uZi&1F8p!!Fq@0E_6z$FXZNT%jF9!}vSo7jlBRg7Mm( zdd9{jKsHJslI^VsUvaOw{%1z_v2$<2HwX_TYNY>Nj&Ur(qE3NQ`a%6!XG{hH zA~~nDw6wfMiqZQmdhAs9AN$cQ=iK*iJh{QX_Hm}mM8i9+qh?_N0UYAuX1UK5Wy|yh zu0YcT30IVIEDKcd(mq)ZLVj2!D_5@;@^~SQIq7Z4I7$B!gl%I#pPT)o*3vxh;$bs5 z_p6k3pMb!Agi}&b^ROdc^Y}7nF8=K{OLOj-4H}E@M*bVUZr#6Td*42* zNN4w_M1W`Hu0L-^{&8TypLz)Y%uiO9=0E0ryZy(c?LR}P$aTo<`fb;`@Np3)Jed^o zC%h;C()h;Csi_5)h?5Vv_U8kl|At>Y?BE3i5-_pgo%bfu_1+>_)#z8Ls;WZDfZD_N z{{4N>A)ZrL=NVyMDsVJ#QCE$o%S+o=eY9r-riHEPn%-jx3!n!dX&v_TyXn`mj8JQ9jWL!(7$-mqW6n^ zL!(5Ab)}gM`FH*5%(k`)e3}OoE?&HK7-edPVH8~Y&t68AOXmN~?8jtBv<=e5oggWN zONqV!tWn`xhjKiot*=kzLJCSfT~pH|_^X-OrAcYFr%NyaK6)Ih;Y1`Fc;!$%;IzS} z|3_-Xedg)J1YLf^t}rOXgi zE#1a+$#L{=-1hd)>D-L^jm(px&izme1xgF$gF(_f&_9@PyP;%MGYJ!$I0c7HZOX}q zBTJCIv;$8eKSUr2suu#gb^Gjc+V~9#+6wRL>l2@s?D|+=@7rIkR9IA`B1OL9H*(k9 z=~l;kgoHSvmb$lPd~S~ZyXq`UH(JAp87?qpIO?B*LE%G8LIr9h=qq#T6gjV964t? zubJVH=7ueV&8x4kk=R4<&*Fih*;72*CcF{aDQAE6H7+ER+rd3>zaf^Fm~{JmNero# zqn)t3p$OP7Dyn*QR~pC`fZ8vn5W`MHTGyW!>6cv@pVei?w0u8f-(Vr~Daft%v$j zQ7N%k2wKFm=Q~+Ox;n^6LDWwy$HLE0H%k}a2@GT=bxge&9^mzy96jlvvk8Zf^kbj` z^<)7{!~XaPGwT~dIK!YPdKk#P($O3oU>k}Pxyt#svTd9ttD8q$BYHa+~L)chOV zmmFQLxnsn=V=*Tb9r7GvVrxZ26vQQRu*bQ4jifuMkSi2@`t;APUTy{kc{}^bvsYz0 zU&OWYb8VQs*6mUFWO>fB|8YSwRTR&VW2AzOoF-fd?R+) zn)T}o;X9-FVyrAo$`^l8@!FusH!U@F2S2}pR{$2ym#Ggl!9jEvOIhrpweJQ--&cQOOs zp*e^%RxQ_wmVsf?T&uRO?mMW+vHVSm`!1g3z%#|@*;sU_`=K*CxEn?$I~^zH3Sm}! z67zKcF1}c$N_^EV=W9}oS*^OVwO**uQ(9YjCuhc1c4`CyO>P`yq|GiWx`QLC6?;eP z$L&I1I1k^yXK|;a9=v!txS|}MRqjNX&@b|j zWT|(d`qxxc_@Pb;GB(9$F1)D9ndK!j$FTNlYlG=*rMcb0!ldv=Nb;4h?wZ&Q%PBZm z9zrUu*5}JY;ud)|>@tw&1psu#YHWA;`J)l*8X9v>C@3WM2;k{1ydstaW=J2w+lGcV zb*g#Y4!Dl9)ySxtJ9E{-IZd`5g)!Ac-c7sm^@{9c;cFZnJ-)}u9F={CXAoX-uEJpP zqwsKP?XqnRf##l1b*t7FxF8T*oV8=kuE^`IUXW=r6S36dtKm?x_QPw*DMxA@|1JMG zk*D|{sY77K3Uf8smW;vT;gxB9nnsR8Ad>L|SMBa1qYE&~MUp_0QV85A>6lmshsK?# z?;%xhA0E~o7{w?kny1KfIS*)SXl#bnCYkpxJv5JgB)D#1E@BL#7Hl()Vmp$_#hjde z4IUG434HpiDXp;X<6bPf(SJ>R1D&CMxeJny<;D)lZvm=Egayx9i- zs6R&JLSx)vWVMB#K5hVd?le{5T_knUAO!Ei5g!VaP1}{K#B$9X&mzE@K=4c=?6U zuUZw?!-NMq6eY$o^5W%7a;=yrUF^l5dnw5rr_j-3J{RBL9F03Sdf`qt#+S518VS#~ z5!{Wh&~V~=!NR}gduIs-C%_Vz8Q)_GK*zNT;-fe7Hgl@I3%P&)0}RXyP;&svU_~b= zWEh@M|AJW91SY6d56vK8KUW|KV5Z=05QQ`tQ>uaiCF_P3Z)U(-2&`{=H|AldqmIyN zcr2ROT=tq=_5s`7Ewe2*;2icB*SaB=hhnzuj8YArz0JT$)C~-nc;FXppLP73^SW!Q^|l&q_MF=ja5Fh>RRX@9h}y$uCi7 zwu9%mjYk5%Fa#pdcpJ>a+fh6aLMR#1YofjLx7}QLs1!FXu&;2 zak0fnGQk2u0m;a#RKCWX93Te;cpQ_z+7&LJMTX$`I>rp55I#5;Q-|aZ=vz5(pubkGY#pdg zCSxzLZecJ*gWTprWhFC|iJ1O%hJr3bV6fyNj7?y`)MMcDZum{BuqLSY;b;v#YGkJ5 z;wmpL%+G(YNd(#+i`}DpK_%){#*`1AOQ*MJKgJ*|Y&$d8j&Io6L7FVu3 z19QijEC2h_KNc6$sjG{jA4isX#AlO;57@uP{9-z^Q@yXMN+_(h!lehkW23hdLwuWP z*3QROdNsHLmCT*GECCe*@91MBNEo^2;Dq6sIAjRCj+SbO21D(Y2Z^CNL~4@+mKgy_ z<`)6wxD1IKudf)L4bg7EPo0((@=~GZqw$z- zC%SpR1(~=RGJOzQ%~z04{jLWs6}bPBWn+5+Uy_2x#^mcf+*+ulU^GFYvzI;^p_r-X zeTxh;^zc~W=NFDO$TAJ9nuBl&1W~|d_3AtmNua21jSUSwO*vv1Z;he`7^knd_i9}5 zK3`1LSg}FUX+JQdm)OG?XSWRXH4+_?Z9&w%H|;9dJ*+~&(lA)qli2iQbo2tqGhFb~ z)0)`$FbG=9%Ibml!+PxEhtmy{_Tq5769$+8=pG)vFF3dtE;GtkMMVOGf{tIji0d!I zp^AJXGu-=DlY{ZrwL9*1w|b~oJo})Bkvi`1wHc{Y?Kf&j-wV0MMbtnBb0_41uOoH) zSXSnPK;@5jLPX!~at46z6CmJBn>XKu*PneBMzO(b9d{a#KK!Lzfga@8M^ege|WgulX(lt&us>N!DBsq{i@1y zul09f8FZl}Fa*j$P8+O(2FqMr9Pvtn%7~s2M-Z$bB>#gUB4B#%J$R6hu7lcC(@l6d z;2uMudyk20Tw8T;+q2VDyL zySm;XDI6IYd0#i>6V>K05%Lg+LRFaLTfuv1sKmXTJw0}Ad>A*ptqCmnDc+| z;MmDe7vTbQnr{q#z2s1Ha%xrJJo$LPA2cTry_-ACfN|Ti{`#eFQER+da-`7-wn5Bh zHw7k~YZ2AEW+sz=O)49}uais$Zu|A$l9y_CYtyeRRZsnhNeY38*S8qhJgKg3(yJk6 z2Hy82d+<~6SIk0ohX{#jixGw#}y9-#g_5%^GgvpDUp&X>1ND9|W(H=yND6E(W#Sb@b@?`>$g| zb{EK&uoVGk3*-_ttewNuy@z%ijE#|+G;+U5=&$~ILO$2iS3wy+$4;y2()3o^-W##c*?cb5Bfk1AX)WspeNSsY9_LJI3suW$tslV01d!tzhqM6YD12r2r`jvm7gYP@2S%80w5(Wt8Ija>i4-d@Y6S`d$R$3-~Y^CyaRM20@`jodRjLyZSW8+f><78 zDYXkH)I+3UpD_!Paz1rcH>hFY{PSI&{}-~8qNb*XaVA0FIYvptS!NaXV{rG9a~a>2 z;G+OWnx{0@3p9Kg$h%*?FK0364(jE-#6%7{75xMW0n1egD2Qv5*_dEN!YIP?-^?j) z$JveO-=ZO_09uNBety^Bj1z4PG}vz%(}9?Ug@u7E=$UE;8dozF;b1O!SK$GbS;c=Eh&gy9xU4|yE{Ad^^6_Oud0C}>3;9--`q25W89SO z4pQ(JTBtKDT9E&^zb$JRliL#E|`o#$>KUtDq5xd4Vc-xI7Gb7O@BwRXNZ>C* zTOdAT!2{-6Vfv@*+_1PIIO1c^baDXzQ3&M>&FO;}6)~}r3|KTC!EW)CfY(3CEQ_6* znxT$HIU0(g?l-XT$7aUL+xz-tLxf#*KRrBQRZoXF>gUh>mm>XjWq`eppJ=ALNCfUP z^dVA-txK(OkO4HW9@z$Sn>| z%{<^n;{8m1OtLtD>g&^1%nh~_Pj2%J^vz3GT}kXIjba5xYm z?EC=)@On|pbx7_yk!ql>DZ`VeXS1Dk*yv_&#uGae;y3dEqNFqN7^0#<)tZsjVPv!= zo1E(6oYY>II=j}ievTA6NoI`)@W#bJHqRw@$;F%<KXC86eP@ydIUd%;O28UhkYS~+$E2ZmOjT24cs$p-zkz1n zhnX*}+Y0te?@{fDItZ5Oeo8fM4p!yq?&yH4+5sdVsOt^U-nd(9W(yNj!fV6wA*M=l z7l5E`N(AHs2os$g5(x=IfWF$gSvTok$Fx zeZMNyd8QXno1&!!R$OG=ch81Hz_|BpG{-Jes)!80NYN<+N#Q+v?%^~?=bCLv;&q#4 zSaOk)3I`7o!Xq2%!8iy6@gmc_(XBz2sGi_Pq{ontc|uU~@JKVPVv%7TD|ygL!5j>n zj(vC8B_5IK*RxaBDi9dKCrSVw*JH=mz#F6piwdee-RgvML`=|C+8hv7wPyP*q|)Wk zIg^Nk2y?MGAR0^>O6Sd1Y$&i+u^k9NT6P6OFHCqWgG69697=aku3S039uwYB&SToy zR|4mn*4u*R_?&H@tSIF{ZX#9rm1lKb-A1xd{xSxQ#iva>#vIqAEC=!+BWSi&OmK2a zMMxyx)@tlyZLPGky>zjfyu5I5@P>#NJK9@XZYG*ndh+!q=V#Xol+6M%-}>EXX+O|&-DdFRc@UPbTCi=$tVS~}}& zYGQ({cqI|cAo-ynAXKE8Ya;<)aS#KR*YDNc@5MUrVV+yW7!-SUv>n>C56x0fKb50c zzFla}d^3S|etKGA>ud$eprb=8{*{5wCyCWy_UC^=$4Lz?d%YTlArY9Ht`Itof`86J z{ni5W_)RP;j%n@v{jPJH(Ordc(6OKA{(~eG@t{%-1cLDk;@HR#3ewx!PFN;>y(DM} zc_{_4!PChP#7R0HKSaAwi?ALqct78K00#R6WtL@@LK+;&DwhWLA}Muovu`~#V-v8u zh0v_I*MAWc?BHYRY4HF)H%XgKed(qe;S^x|6uPC3p@=_JpKQB=w|ZN5>sW!hV8dM% z`~MQv-fm!5VCX*%P{>^S-{8D$X$1qU7h6mQ-K?cq$!hxjG6?_kj`-*Z|Nle)|C2oY z|Cy`&?>}zn2xL(g;dKPefVD2odD<3}2ks+^>UN*YbrQu{zMY4sMAz};$yG=JIfaE& zHH`UuDlX~cpFjo~1bb6;A1M^&&+>LGT!JkCSzg$fT1eVh=Z_3QqI<)(=z`vD|~GIo6BWXxzyMW;S~q?CaU{ za1uT$ExqPX38r1h=-`^Db5hz7Jt(^Bs|NpD?(B)@j8=pLorz z)Vy|BBwX0D4Do*Q^+;@Dl@;#5MiDcp23)uC@OU9JB`{n5>{LHL&M1gxlG4)nudo3X z;yas#(b~wKbO;GMDmke)a6kjO-OooGa8b*c;6Mn`k#y9#7z3 zqTPchPo4}m=H-XOI8Si!gDrYaFyrQq+K3Y+`tIChc@cprU%?=Y)b$nN+wB1imFi9X zaNOty^^T6I=?$QTlobp!pK!lnv_xii12Jmr?LCyJwFa!fzhdcE6PJj z=jCX3d}BJj6S|`#`W@>@tF@%0m{`F)xg#$}eiM#rDK8Xb8nq*jc|VdK^14%7>Cjl}Q8~o;iJ!kA1kYK zj(4ef5XK=M0cL*(JOFlh*FPItNV7z3t-E2EbLz+Hs;r55$vZz_!~GrqTk`NmEt~AN>d{YQw?%UV7ya*z`2nBD)3O zup>7q7V2;hNz+SL)_y}I!pKcP0epq97+bfrK2}*SWj%oDcSDU?GIAx&p+Lp)$6#So z6tk);SFXG;*2PPRN$_~LpgUt?VabP>6cg*W?cTi#_~5o~DHQu+HZup09ovD9`fgbC zp;sXgvPpfUv8y%+JcQ@cD>&T4F0!XFOXS}Cws`aAmjLy{0k4D2c?3N73d-EMQD4`9 z!6HJxK9dP5w^TZM$&cPZ^y+A=g$26pDe<;&baTPX6`CIh^VQ!G(hIR~Iu>nZ>XKwwG{wr1FHFqLAlrLgd8eS)DEia=-L1{j<`W>^og!Lgx> zIR=*2I^AVYDD$iB$C@p)uvMP512!!HF9Lr&#!bRb?iCN4nOfWO=-02h24TTw0GD1` zR3!YM{~#J%Uls3_j{&2wo_qkV=wZRtff_&fIMTsYfD-Bu!;cWxKHTG0gdHZQMIclTRZ_pX<8TE?FvSm|^>1^;U7XZ_^X z@7VenPD}d~=o+b3uqe+*sg5pyOZYRSp^lJkEs|RdkfB%(RwF%w0Ug~) z62Y3ifA@}t@>|IK_2t-nPkCu+CoDKFAmZT-bl?=d8zTRj8qEbk(hv=;$kJ)j_$FZ1 zP;dy&D7bSV&o1%QvV*y>h0SZovLOjHzJ-F5n)tNP=Fpb8m*(LsWzY$bK=il0_L=O38*p}mHkeXhAFnNdCN>L66Bq$FJb=j?veveVoE)0~-8EC|H!@k1v_>n3b zaQRypejN<4!KdtbbUP~56f*iCnBwq zQaKn?Y?L|AS^xI)O>lbin_ooS2w8iLbDg0o%0> z;Z7X=(M}lt(iIX{im-x09g5JUn?h!SqVS3Ti?{axsw&&Mg^xL)A_fo?P{c?Qi4w$& zh=__JIZBqCGioaWB0W#ykV%M%mk&$Y?uV20#ccdik>4uW3%d0ZWe5|9O!3d!{C8=@L zp;j~fyvc-5aF}A4dP#k5CYcrP6~v8~@?N|#H2bo!A;8nf75l-{-QY<=0w)ArfOHud z+C*UIq&Kbh?CO~lo6P|o+|BmdQ&w0=^RnQ6Ty(3dlQ|iE(87`t61)!*$C~blfhnd? z9a<8^YucAEYY6xY0{}5fmmVB6e@kn$jn^OsC+GIZAm|aG6MDKOk!rFDo7X8pXA3Ag zIe#1$;$9y=CP6@!$J6qFn2p?7B-DygJskik*N@H5FDW1$DDuuI!^91XO3C#EMK}~* zC?u5g1qVi!GIK9H#2xz#Wg1+!@7FKMVDk|1%82{)BH0ONic zo9TR%i3#CBcxuQsM6IZXhjzHP*9oHe{u+tz^oVS9U)I7H8L&lcMyY?&a?#XNhD`|0&3_=^ zBaNW3?>~*mGhUmugG1=X_4GnVdOJ;aVW1;8UdQQ&b&e zHL|yC&`1QXKRTTyL^Kys{xY(%?r;E#qN1-a4l9$r5hXuO|J^42y- z-rM~v*-#LnZenP04+=j}!uj5R$U<9V$)>UyGvCkVB(>;ad`2aNjqcfxgSdu^@~<9) zaBn*eXHHX7`wcK;UVZrdG>rtH22<)QLG_Y-;p*m=2Z|&Gg<(H3cYTOUXR_9rI66Vr zCnzn7p!>fwkOGb~L5D&l-qh-+@wBb8vjo~V@Mkt1JTprp?DhlYnb_6*Wh=C+>px=} z8^OUOq2c9w#`wxRV`R;sIio2=K;+Wt7VMZUL3^ts@4|sJAAXpOzmZEIbYaH@^*()YulS8*m(n zy*L$WYX*{#;sf%PUbYdFIb*A!fs#;M96$TMwUz^M1PHulmcHPH>*7P?+wMq6%hN5T zC?boZEGEi@TAWT_4)#PL7$p_={(FWRnZl`8xiH1e^tdpo zhIR-=urelkh469XusrY_9b4kTnQ*}A+J65&f8oMfalvXw*czyw z+P9DU!9Hc>C(BDRxS@!W96~V?VLLLcg|gvMNX_1M=3v(4Z}>+G6pK#IRz+#YRM_5iOt zkOUMbEkuS0b?hiZP#%1TKK&xvrVL3cd)qWmsdcCs_gU2mrOLfR*$%pVPMOf~u_K)* zujr5oh2=w|>4fYJWbyNZ_1XV8CV}=CpqkfKtcpwu{Ba&$3xh06*`@Y%5QpyDJdc)QU zdyrkH<^ixslOnowob2g~Qw&7Q{9x8%4$+ZvVY|@=iVE`=VlYM^Rvx>4vm9zOaTF1n zU>%^b*1BAmHvTChV$rQ#Uwy-x^QSr;S~nkm7WzoK)L+7{-k^lNF6=_ojZB6gpywioIW19Ysym4O?)VEy54&5n@6j0 z%~A}JExlmU*{Bb>i$$B$v1|NXDAK`V^tLLycTGej8@_%~gQx{ez;i+FjG|VJGF7kc z^OM1b4?uvZ!8H38rHBde0X)m47?OY?U6`}6VPaUw0h7Xlz?gw~uO&f}!}qe7Zdz{b z?cMVA>%(P+)2BZ-)<#N=>VWcUbVi)te1K(8uX$VZqenKV8{k64)Ra1@G~6r*tJ+sq zQ5hNQ;P`R$s5<#Eak?-oQ;=$JgR6zlRPnj5@E8fJ2pRqPHOkrkLu|E3hzf7|&jSh_o1W(`)`k z1=j2Ub6t?-`6kk1E=1KQjx+EvS{&m`vd{JU&FTPY69GKqNQ0JbVb?spRnNO!zghRN zq{B4i-Gdf7F>HB+D2mW_2!T+%vLdk96AZklsN!9VVb}d0B_)Z6w?BU-MM!U$EXqm^z)oUfe$$b=_V=aOfZj zy*58ZTPV};U9LI z%6%O#RNOEI3=<1zJ?(}h?nm`xS$c7Zk*V){pLhZnb(oM z5ICdrxenx|kg1e0ia;hT?>JlQ;JP@Vyr;c1H*b4z18v))0fL6T`Z7vO4qu}Wd7D=G z`w%Vb#koWjBo(nO7jfXIaMGNyn%F$qX9;;qW=k!O{Pt z`5%JEvhvDrsltV`C7J7Qb0p8JNHbSFKufy@M40bC=vv)`zEsAxJnnp&4lPTRe46JE zS6e7HkMJhn9}ERp)RZvl^7oCNEi}m~R?lwbGf<+3L-l)6A3f;y{OVnQT&Pb>+vJd_ za}Sp%I#E(ov_Yx2A{S9v!Tg;KlDE~DM?;BNPrd_iF$9JU(v zG_Pemrl?dIy4|GbXF-&`i3uYz9mw!#_4Vn&gSe!pM|bO%tf(B*vF^5#OxnM1OW~2_ z8bAl;e1}0Et?8%FpHV|l3g_`*Fh^UflDI3)4Gb`s$Vgo$Elmwl-9DtBRWXa**M7&u z=z*g7f`;pWnC^xRv+6EMdyC4-vg(ou)O+#KawRm1I>~{5V9AQLfwMNW-J^jNz_=jLd1s54;4oQKaNxPLvfD1wvn3SxRdynkJi+U!RyPlT4U*VS4zGHC=TjkGd`G8E^_0`|O z--Dh1O9$iff9YVn|GNf>XLje-N?HBqHzSV!r`qZ+p|%RIxNz|zp%>`IrqNU*55Eot z@L`y(=nG!?b9cjKqL{2n3=FkQr%!vrcMxJ<7m$`tJqbhJbllKpl-(=0Ig<}iG}7R^ zA6t<5qK&ow!xh2vNICQ?dj5QR@JZsTy-spZkw5~dt>yu98BinMPDh(;OM&;siN9Qc zEy|d<5mM?2mJEJZZdz)Y@UI8AAbsmJ6Eid8$&=0~y_^2I<@79HC>yNKtKwy?&DPd; zrfzny!4a>!qhR*|ezRAo#n6g|w4E2TEWNlx^Ye8HGlsWsDb)vI5s&C8Ht*>1>jlS%WdLG^SXV8Ua zXCG1vG;aUVLNIo98_d)P_j6xrZEL$W-gUlKP=Uf@|7D^{5doJj28J38wMp7V=h7p}x*aAAB=?Q-KKIr+SvX*!d zj5os!V`k(xs+P}QWoPHNIpBc!jN}B(RDzZZLJc7G3t#lz03rbuttWUU%q(|pg)dzy zmQOZ#2-|8Byqrr>eH96OQOzqwbbu)JmCjjvB_(5QDb*Uxcq+r^j*NzjQzYyyYHgZ|z(NE+`x+coVb+0^~6SJX@9{E@gQaZ;isGjiJgN?oR)^JN!1a6h^=E51+r$6)9X zHcvxub^qBLfdbip0C-J~djmlsWGCfPR{;-?jO#dK^)E&VEu&0;|nL2prYioagzK!^k%d9#v-p zQz{INf%N62P0X^CrS}v|zSq=vg9eHYBvDIjd`$3#-y_4q@1X9S7_=60&}u;8e9=(_ z+TUXUE(l*A;Nas!X)nQl3K0vCBr+D{7b6f_;5WfsqCVAn9!}as5dxC2dPOh~z$(I5 zVqv>A?d3}yQ|1`!Tl!k$z1aTob3IG*^d#rCu0(Y(QK@=;9@EQaXS?Yw#|kt^*RXNb z)X+;=26jguYCA6^x()7Yp15nLw5wjK*UEhvpdwJ;nNc>yT3bM0Z!pnKqarvd7K^bQ zje-1vl&eMF=Fn_i1LN4x&@j8aJiO74j&5UoEuoI)T+GmKvBPY*iTHe&WhrY9H_e}g zzd=ej0Orje9NYVbGk?l`6SbLWK%Ln>XxY;m7HwPIGF253#h z!hODv-I=g_;njEC@dk2Hh9G-7NX7L*QnIS9RUd5&!i}WD;wJhOBNt>ol;aeNl#Xk=hX9s~gcc}Zl$QPVVmio5{5X4AK*5UPdpZUto(FiwzKL+j zdkkx7ik&-Wd`fLoSY){+0FC)`v-pRnTTipXm{}rZeL9gD7O@E(gU60x`_YjS9uA^{ zZc6i6>iCM_{VRF2jQjw0%z0#B*3&57MMw z9?cXO%RiSn)5d{94keZSAy8D|-)sO|OjMZKW(&_K+}ei}(!N^~d$77=u8dY9DBNqo zbtiLr(M;4DTQ+Ydz145Y6afDNU3nLGcOm-m{d^|-+yuEB6Xa{6d@+L@-D+phk4W%Z zb|C0t=O5FBppO9Y?g->I6-bi^Uu_buBsW~**lcguljP(*i??-8?SofGYBr&JzM}>j zD0@I$3gQ#-I2_iH`_}0JPHl-hsFmIX} zOrLcDiv%Z5!9QDe7tsnMAQKF&iJmxuKro4bpD+7-Yf^z%4!U_6JI>kI9N5pj@B^IQY^W{_j8fT;a4{TC zY8xC>-D&}S>!i=M19Ie8#80?yJ=&HkK&V6|m%3_T|z!3iL)T-~IQIns)?s z1tl8KJdHwcWNhZaW5@Cm2D`dm1jrV+^YHOG&&=?m`*Zn5>19NPhwrCNN3GK^c9J-* z6$JG`ZMd7cIHe<#ko6*Tj==XluJMUdpfU{{;tqKD-OylS~dx^C6IX zz9O0dvG{DaD5GFA8q#mIh{AAX{qTBMjXQ@UJF`#hl;r@Ez3wreFb80#)cOPpZ(C`T|pIhJ(dzQ(wxA2~UXfMx;f zZ5hGE$J;IP;SRQU-gRrv80KI)3>UT=P+MI*e|`;^fA0`5@2$UJ_~6%0!X*M}LYcgI z;s>)q{_FGNfdU0jxA$W~W#@&R1wMB&iJRrzrSDdlVx4zavA?M3KG-yf0WMkq!*578 z6)#LRSiOJGAeuly3GHuxj275E1s{m{fJriDi1T(#ZYRufk|%b085r$QaB5p62^2+lAvDjE5SB zky!Y+yMG~0m&co?F*$?`wL3A$E@ggbD%3xgL&HwX|DiqRK%(;=OG!u?wa;nw1!Sa<;QdV z&1Cb`fbJ`cr~SF)HS0MYfRL3V?ek{d(hmO?)^R%Ql?_C!?nP|fcC$C$d<|yB*IGdP zYq`9r1qy^0mXiwliC{JEbwDHC{~EKLt7}Q3txLvd^*13QN07UqDo8Iri{rQ*2e5ig zl>Rz2YeNlz3#FJb2K7-p*I}_H71K0i9nT+JdxQ87@Huh9oRn z?}OM=2Z#3_BrMKmDotxbM^K<7L5<$r5>A6a0YqFULvor1FNWVsYUUb8t<01$)ec9Wy)^A7* zMu`xmnB|Q|?%1%s_}YWa0~&CN&b~;#NJcQKawt8Znn4%%;d|=*$}sy&-KFw9^@;n@ z*;4PTT0W&!(SYkWM(&IM_`S(IsXNe`?~_g~efs=RL;85Bec`sfsNumt+Ok#KvbuI| z?Cme;?$OMwPO!CfdOG%+-+TxB1>djC@%akqaLmobZx!p@o z&te?FYpxIX2ieJ-!_ix|MVJMkYstMGz;b?arCIORw4IG|e7!zH- zAFf#xyW<@JUCq+L5tj&lc(AawTm(@;HGH}$PW70L4b3O3$*qWLejC!+*{utsr{BDJ zqx*#x*$7GjPf(E+Axj6`jh!TMX zL9PsDuYc+2K>Xz+8i-2wr-r+Y;A^w%#EHxFx1(gIyVtwHIB%T;CVV!Jkyl*0bdD$| zKerhq>9;I-33xInz^pD%FaV4jqQRBaQmPJvh+_Xq7EHu_f||+CPnu`KzqgnANIi`1 zMWg3UQ$Uqx2Qipv%m6}0YD7=eH$dN-e~zLOA3Stsb}d@1NOL_(-=uk458(E|{7sSs zjFj*fir?9V0Wx^D0g3QV7CoY^NGWt9!+!ZJD$ybor{GoRfl5%HIE-kKk)Yr55N$nQ z^*UPKPi}{WcW~&|JBA8(?&s1jhE=!-e3q_HN&as{kk441A+i?gp zGJYqHTYL+#{u0q#H^1F7x%pbX5y+DyLu1bFqTK@_=0WAc{J zk%Y@G{C=l?ZvYJN!cE*Zeq07PnO@`iN;6AU60BeioW591rpL;>|7`?b^-0GaxntkR zTYPA8LPJ6b(Ftj6j1{K}Oi=ha)NQ`u7KptY_;^d)KQjyR#*u|_)tP~Kwoh><1gk)g zWaQ)X1bv(S_{of^8d?2QV1MaEP_r-?#RD<(xQ21=js zgd!_P562x4lQEzaV-Q#4;ZTn3*`=%G@h?n8yz-%Z;MN!D11huZmrskHe5C=#guvp2 zMCc%@{T-;nLFZa?P2P|XO8Sot@zTCm>4}L9ioE^6`Mb${9_?1>9q9dsJu>>z7aYQm-G(s?GYu; z&_rzMhu<7kdz;dFw)i0rQ9WhhUwxiyp8#Qih^{HelM@J>>a~yopp|#Zc1{?PlaTxP zFJ`4$jvqt-*dT=tiBpiG1ko06%XC3?M+>J8Jf`zEZ;Ha&gBP3+$ZU?HcZE+t7px#e z)DkKsBh=GY(?hCenGe@3Gmr0~GN%Cwz%0GXtj?DVwYN!l?EXDo2@q2&q1UJGmZ2Dq zC6F@REYx4$)z!6YzxB_Args>OPzFs$gM0#;(Ln=Vz{hSJltf*w_`^4Yib>}E8seLC>PX%xRr~Rr4ZJ>b1%*klP#CabCj#?JO5Wi&LjtE| z`k2GOdT7w^hq#^=c>nE;)QsL~C!~)aZ{Fl0nEFi`n#YzjnMZmjKWnrixN*1T^^?gi zn`**CySH(+kIW4XeWE*i>g|Bv2AHm+9}Rke4u@6+BSE>lbB7a*$pl^SQi}1F3)*s( z3FU(T#*U)O9i6OgAqribqvC$utYtWfkXlVsqrVKgTW6=wv9_L`e00&)I@6s%qktP! zik!+ybSWN5fhPcV=87jA_38B>e1Sp%?WYIPZDudX&wq=`AMh|bL#9MFT3c1tl=0<6 ztDtEgV_=}dUWNP7Qs~h8@=x=l+=A0?)Cpg$8fFLJ9oQ>p@Ml}Lp7fUv2ndkX{-~;P zuVlb*u;{bwOMp)}%;BxU0PM3WvRk*lHp7}+Kv1wQ)0Q8KFKCe5-d&{UAXAOm_88~| zo?MSVSnGSCOV5T#7#)asrE*Qq+vpUi=j(FP6qJ>*v3Fqrb)l`wF)psXJUl$umzP~> zUOcB;eBh*-lVit9F@tG|<*_X!xF3Lwu?|TY(>TpNXROlm*+Cq392}x&wMPi3G`}vtl*)}+3u9Ib8uKLXnKZ5!n$VtBl zet(39L?o0F;;tJHLSyvo+2pqUQ~S^<%d4!cydw-gP!V%JOJFBGEp2YCV%c%S=C)ni zNob?9tz8#jJgTw-S#;WvwlG)+AVL!+$wZNc(5$SbReQi2<0$VOG{5{}<$2wwy4}Li&Tj26Q;cHS*mLohxT{1l$B7 zUipWYD1zEy7XHYvU7-~iJhy9m5t{~b>gxV>uP$t3rOraH;@4+(lYm14lTfot-_{Ba zz&9{Rk)Lp5t?C=0U_tjbSI6eZ4Vh&Xfzx3ik)C7MA9( z3}qyBo4RGUWKkmuT)GqmZr(bi18+4qVi@F60@gr>!oR-1W|BzI03iolJB!Ax`)ivu zY;3VcvBa$Lqc?0^hqHpd5yd6QrCM7%VCDG1ZgJzxJWu;?M|$P1;#kN#!ll0kxbGB4 zf*Lv)9K4=jflEqKHY5p;!q3r9yPF>AP>Y=``JN5Ji8?LW(Dsf_FOO>l621GrzPT)N zong@Hlw>v!YJdKGT0~SdZJ|zL zql_vGDYA%;Z$O2nF6EiN=U?RN=fCTy__p=-XyP1 z{nXi8lOR2tnN=S@eq5=<|1M5L)aZ`;I5okrz7*iffB0|{vm7^#D}2TzQoK|;y)?nD z$^Pfb-o;{lE$NBu%N8?ijkf02m5%$7LcK$Q6-rKtVueWlv$J(mfS&dhH z5<-#`!3l@+-?uUB5C*((bpev`jhFXMURha7!Y=(d#ED(7KLh8M1S&;bUDz0mY2`k)JPE9^!u2NN1! zF|~cwOeq%Zc@N5?og+Y#K6`f3>3O5JOg5dfdePiWl?LW9Cukamg=eT0@k^)AXmphY z6(J!z2Y);W?GJ;pbaIknv`AW(YEfvuT-ec|ugV??Qg8Z1MI?~})X2Wn{Pl_Ao1@TE zFE1`QW*ng;m;KE69Q<2VRn;Qm;{lVg$bQLbZl*(d{`s?WPBKacl;A2gNf-{wEd6=L zKJiAtF316e>BT@dR7Ns=0aX*oRSOMdHaSpBxrHKOyN7$sRm%kP?{2+93b;j zUzlHa2hnTPDB#L~m;iEHuB)hwr$f(sj*t1?m`|`5iZ3KB6O^sK+ zzJi=Olp|T>+%Xvnr}wbLnE%ds(oa|0iH7=?Eh#RbbUy`R1dmr?0BC2IW-ek>%=Y-) z@|Xm(L2b!cg=}D>V)0TeEG(e^`dDVTd=`J#5 zG?#Ybw3W`X69j<6HtunfVpaocRW7gl$6X*p2MBj!+SfU?J}S6kk5K7Js9pn^bn+Bg z;Y;(~(T@cF$RS`8C|YFumYhe%$2E|$m8d6CCN0nPpZ4cojBkRZid{8Ob#B6~E`8Sg z?Z=J7*bcF?R=__9Dl5v?$3&as!7tT`USs+edm$h2^?gfct0c;NC;NZJaiDm+3S1VD z!9MN*c8QN%_|f9mvq#V(BGwIHAa>hdWCqhsgM{)VzASXz<%bF_nTuMLM?382hhZBM zh={0F*oE@*JPJbzYs1+W|NLVC zwu{P~193KlsuGkGo|a;Oi-A50Rv}fn(P##M?%W1i4>`4fg|F6{^dfA!R{+Z1YSKO? zqbd!^xPh?EQ9{DVz^(OrBaxE}i!Q%o7K4dAOBFLDcqha;dJx#@)9vK;|7y87hT5h^D)RG za8MqDHi0MdaO1m+#~|UMv9l9{6-L|4s47A+d?z8OI0}T3nq!IJ?*OP(fn_%W!vp_t z|ffuiR~{J0A!9fl+`%Dc9D^h#n*k!Z4qK&W(F`yh2E9jT(2-X(}red>II&c zK?~at4;TVWhr2VPDQ+NAsl7wa`C{g>>(hY^qb*7lH@7ehoR|dxPXpK-QpMCy13QDA zgdYmlp940qabupeu(ubg40BjvVAyLA{YT%CoaLNCiqI(_oN)6zf+r0Nrr!vxzLTJi zslwt0RK(pO8z1hi&RTvvF}$qgG_{GYN8d_r(FlD%NXf##=jIaXn>T!>#cTU8Z7ShX zkY3XemvvP`L4hB+&}+T=Oc0qyr}eL?s4!q`3Z}jn)F*+eOLSt;bT-k`xMaQ zFexuKlJg2W(wa?tzF)s~g?>@~M)yHao*W>p;_q?1AF_?z*AsP?Cu436);j=KQ5(3x5$O!_LHtLRId>%-;@1NgC}XqE zg6nv1ZXzWJokFmvEIT|Nc4pckJAQPzU3;UdnKEl0N0FlZQtW0VtjtjzVI?8dr<6#b zXhr{=ZLyozg@ZV(<~PF398h8wgA%p;rfniSySn@fInclM^z(BH3+ujXt z&~0E4JrLx+vrKS0ArD^{+=QK&AA}xTC~O7c#wkpWkf>ZU3jX8v(ep-`rP`)Ui zvLG;Pc&p_C6@|7@^Jr|jCc?KrLCwZRW8zbgDY(ma>kdNKgXioguUh*040t(D=Z47JR}!`Pbbb25SR_G0LrkoCo^acgtE9zr=dwZfC4#nTh()_SieZmRI49`MX!jpCdtu+kMxgquIz3f;IK{i`` zzzVELJ}S`ZFg@%tW5fq zq%VZj>r_7s)!ed`Kw0TN+VpR&fBt0nXAXpH-qY&3<_eASw)Yv5#SR{mSGiKm)%-K@3sG$U{M% z*&VAMiv&xp@SfVbW=A@!o!HYDHuEAp8csB?h3o-_&ht=Em$ zfs0roF%L1%3^08(Rk&GF)lXR9Dq0)|3tjotzLj} zMjqi%-?xOv_tM9lfVcwcyGrH*aZ69@)G(V3{37z?nEut3yz;(D^1T-6S7ku z1U;9q>|VcNgO{`fkDws!v14Jkr;lL9*jUF2@HIeY%KF_-8O{vc1kUo3Q>QL_6o6I@CuGFj*CAy?MVPQ_v7L=jZ9`_^3_6`wSLp4fRbO^ zA&Ul8G4$=U5db2*b3Yy7&`iAYTb`tGeJ7CkLT?WbOlg%t!_e$vsm7^&zC8MLqoYTt zUVx~^08c*5#Cc^6%F37BbeYe;e_szD*%XXpfC~65iHvIL>YXYxg76O_;sp=|5G9Y0 zAO|3ZF$r3$kkD9MhhhdWT;J2ifYlFwb~Wys^pyzNM`~*1mo6>U0i44GA_fMP!R>;v z*-FPpHy!7i$!J98KrLvs4Kqxh?;GU}6VD^+PV_>XtL!oFml!sOGTI2ydo8RLsm~a# zCv0Vlr7O+kKDD4})Ydgd3+5ggd$ALvXoF(LHJ(LoVM^9gX zCR6bXWcnw{hrc_$e&C~y=67KCLYb%QA25^4v;qN9foKSp>d z6kPuQ2h^VoLqodq>X12(&pL^T1g9W!06j3KcgEd)?4k^UGojUi7P|~%T}gzk{`Y4T zs94e(GyfafIlO{)suk(bteTF(o8+=IXN>wOb*e5Sf%pYspUWLnAj3Y7kJnKnZ`Wrz zbH)$k$@bQpv_eAm4<1}&jga(4eS}@L@f;?|fJ>Mx{q0pl@qZ($N7H$(?wJKw%lZ^m zeXTGkIT-F4nVM#3i#+`-B`aHrc{KY482*Nr3M~%|PWbz8C;!VBkG&!P>BRGY&SPhf zmUn(H|KI5A|HGg1zhle)`{N2zKW{q7Fm{hfIw>jD>*@X^;@>I$<}HnUM1!W#`T283 zOpGB+I4~IU{Z}gIN6k!o=_LX&jSdbI+-Fhr@8_2yRKiu!{n_x;HT_oh_at4uzS88$ z{XvIhY&muAM_%4;q!rw%Jg`ay@azAmxd@_6#Fj$AZnSM+?_F!^+O3Tut}NH(3{Pj{ zpRhAlMgW*6@1l&OpwL0K)Uf?bP_~j19A?om^7+LBQ&5aT1JH3IaTt?1DfaFafusb5 z{5#+d0?P~IB!U2@pY4SwXW=qgXd`sWJX$0mio3}3#yiL*w`gGveXao3w0y`@=*5S{Yc4x1Mp;NGIz1Bt? z0B2VYfWkm&SwFN;QJQjrO~H+D539F4aIYbTAX!-KBPbl`WE+F{Mgptg#?6~I{kmh& zIL1Q(AulxkLEUMn4?o^5@`6@-#m;f%F6g``7F1J3h|8Ljrc-*-$nwxT(|{lmGOh0u z$IwH9jVhuWX`g__PCOY6*b<{@`*O`Xx(=j~C#D;L6ri$q1Px~#{v8#d0tZ?TSwiMx z#H9B(Sn91iS$>egE8<@#h6&i5YnA3E#CxhE&HeIF(YoTXjRh?)IFZ|4~Wu%x|Y*0$$<)S zvhgR)CN<*AL-1KpQiARaA9@(OA=JK(oLt<*S7cYL4mAM@i zv%&bf6EG7R2jc-VN5vsN5Qjl00H@P$8Zf&8ylkxfYagy`$KWg{h!l*`VLPpyvmSX0 zw6up|hnJvj+HIP}`mfmW9|EYX?zO@UMyg=bwGRx))O|}<#)B6#HHbaR$k-8)N02b) z`t?7-vPnRo@3V#Btu0Q}9GPwCtHJzXEnx_RF4z;?lC{L3V!~)FUOESuWhX2T(8^rn z0Ez2Zv$e#t=g-^9g*T1$MK0$d@%{?I0Oy+|GhK7wZp%IJ$xh7LY$W?D%{-~j?A+HN zvI*jfx+J?L$qANr(e$`uZ;8K*_`#|M6m zZo*!G^fcg6QzV8hFgiJjRK*P5fRvIr5v`7;4C1t2-T2POcUatgfBsSj&0W||12j_` zB8G@CGA8GAPfkt2m2*CJ+rOUdyM%oIKg$be^Z)I+_rIJ-{U+Vo9i7xn)(8IPlYk`7 zuZSxD{K4(Z()=Nv?()9(>e~NAEFx%at=RS-1;GEznf$+ATOpmpvwTGg>;$+Xe~tijKp#T8U$CZz+h)4y zKt&}75y_!L`T++DfISXC^O3uAO}aQc-=7)D10w)biz}cuZzP;IQN5qToDjWVi+?iR ze4&>sIvx}tJS-j2AJH-;hLZqm1}OHrE)&==j1$m&A{_*NjvW&Zt0&Mx39%@~eicS3 z!XpQHWG4dMCWv+wmGGDe(<>X8*(9~btn59QRhWem1;Z+@{kXOIV9R*|WkZF5x)d2> zK#u%z|240n-qO>Hk!~r{So&2%f-6|$Q}?~Stud_NnwTi& z#4Rd1uKx~z+>sZC#*xJIfs%UUu_u_BJFpsfOrHPw<*_ot^zr0f!{mk}{pD+P1tlJS zeow&l&=D0cBf&a2^YqidD>I2=WsRW-jNxx&(K(d(`Bl^+-b{bAz5>YLi}) zY*u5RLcC7%=evDh8Y4qky!VEyU2xG6qRQF6v61vpnO@z_-u>ln7l+nonSpMOZobBu z-PUJ~H(qZZe^chch^gj+P-G)B_|d3qW(vbX0chM=pd;3hCe1&N0|7C!$w8t@-Xn@qJZ+QPi)jxLhd z)WxX=aZQDl_cKr@Gvd8_vcO&Q3ojEbSG_JjD4pbQRbP2iGBGkXR;s{ z4If2G*jv|U+NL4sL45u5+@hAs^M`Y~4Le_zY-mtkZihus7&jtx~c$;-uc7gI1bYvtg5{1X9Y9enDxv_>o#TkiA97Su%(v8G*z_0S-<88V{!Ps)$` z4KH7Q0{UXK(86!>)bBzL4ihMzf@#(1dPE_qkoBsh?K7*7kG;*jgv+{PU@APU)_KW zqJ3e0zJZ_}0$!p@?$#t-VcUh#Ym1A+;{C8NticqW;d;IJI+F(7q~20~jUFgKZdq6) z>nP%H4RSZaB!E5FqEobY*RBY7Gd3m;hld4Lz%MKc)xr&6Y^J&}NV{ugl{%EQ>^3)@ z)uP!uwsQX*I7mzuYb@@75p$YDXz@oL&$e z%sKR|yu7@c4wbDgI1~Bx=_G-ZXHtUTW5Lha;YIVPS#imuDn@d9)~lePSTuZY)ykXe zzMO}e)TI0}Rj&)1WRi9!g1x9GlMU>k$m#~ok`%J?QhVN$Rb#NP?daw4NRO30@YV03 z10DhZJ9C-*25I3I1q2Fco%Y_}mHlj;{SH4JvFT0OLvS*Fc^XIP^(VODpSI44se(}OHTZwnb#w<-9 z=m~rR{cgb@j=UC-n@M^7B7(OYT^?k{dk4o$Av}w(j)WEg&b-KM9-(D{c;B z-~t+l4R|NOLDTH{sT}P;498dzPiU~1MQ8xWG4|poGM!|UmEQrILT5>aM`-0Od2K01 z){cDa=&&2yVeZz<8=c74wo%9P{%Jo>RP7m)HL~?^kp8fU&f6CZx-c!_5^MQqPzu@t ztBLX~OxadIdF;u!otEzo)-T3YZ-|JAG21_E!p8;t2_;V-cx40b-Ro99EtQps69(#{ zH_k>j5&GXk?L=)9zlEY6cn0twRs8PKZJe31Sx7hovm^42X|dfmHMqkAeV9-O>47XOtiPl5Q$ za$#CZ$hT5m?tn>rCC$>;DTVnK@|~S7j9dx&gwc%2Wc58BzR=)cDT&bQW`Y3Je_D3G z37a3z65p~#u;~W@3hHOhhN_oX-G((&LSJ7Wc(EZkQM3v?kMMQBHs%{hS-DLPF-8A6 z-TJM}KW+MHhJy-MH*G>4wl}OY9El@Aj`8rIpgn7^s~Zh?{T+Nr^IKZ7zIEq?EBDuk z>A97iwf@xKUs0iQ`O1&i1D-4I9QH}7<@oG=Tj^{v(y>CNQ<##JQrR^l4C@hEo^|WTRI=q;kn9S)GhTh- z2|fjt8%XD@VP~tA{b&P{n5PJXj45lItE#H5w7b2~BK+zT4BMZoPitt{e=shk9~aROID18~)>YO7O+5cqwKa2JY3`x(UM%H__dcl=KGd#n&OX z`i%px5WnI1a$XB6J6f8tYb8mlnkQ#gV@^**asds=4Zw_~k&zHW9}~y8gt*V@7W^5q z6B`~=9F+F%`Sh7`P3eO2n;baq7#U@mIi{5~U5!2y zoswM-nEQ^bY$QMxuKFaLZz7n;`MBO>HOp`)RXII#v}b@q!!mUTNdp0CYI$+@{{2ii zGy#hrFpsL%_QGb=*4B1uhpR^<`sq5LJ6pjZ&&$`BQG__$Cm=iMna*0yC_OtrU{zO&P`2`%ZTI_^A3>ag+9ubz4J>Q(y-WYW;|do)|Lw^(5VgUftY} zL_r)HxC1|pSMPVilY)ZKEs3qeRj-FQ?&;a~(79A#a&mGG80CHL0LU6UdW}}DkyjNfuxAYXCPuFHslxa* z;xA@O%xFs<IC1l+|*;_5f(-h^xnmQ6(Q{zFn{!I?sdxNxb z_wK!W=&ztZXt$M|eA+~7<3OI){hZM656hN$}4;(%6U#4-0{#33BN>n6>#?Cfbum za{f!wvEi}KVXYGXL|7zc;ZzKU#|5YmCA!6M+?>Ejsqm<%J10(j;4~Y^)tm3{@AnD} zjM=ZBejXrl%+3j<&_6+Qjyx7*a~lPTXRsHOP=!X2T14{9C+NW=fpwld8k(jP1N2X{ zuC7J9t2k`}fJsDVrUF<`o{W2`sQO_sK*Tq-xbNDH$xNIuolcT@L5t48dq~s8L7E@l zU(KgmZ-ShRMPVWR!o_cP7J5^$NX&rI4_Jg(pXf4BZak6*NYIVKyR<5jklZ`I9 z?}37YXDKZM*O)Dd8feMK;D*>?INk|%_FF|hSz+k;18$j@Q$0J^b5ZOK-(3jy?_Ri& z-fU~`2gtlkZ=Cnd4K)poe!%R`&$rb+qv*csiIgE4S$knwtny?(1pgl(4;0INy=}+(5 z_PJp&6^s}EH<&~!jW08aDhjJiO6)c7EzbmahS|>(wl} z!iz?)Z3+(}!hU%vMi)ufOE)(+w0a{jd`zSQX9Dp(Pq65IMjFlq`k1A)wGQkEV%X8) z&KyeVrXzL?A2dYr<8=?z=CJMM+~5El0VAlBf`al?iUN|v{~!&mhA)c=y5-#SHuPwK zVE%P#HHs8*xSZJ&^TMO8*;nqyxx*-R9VnyZQf@=4WrE6N4<%(NY#L->GUOQyUV9H_ z5TW4f#rO7Pd|41ItCtc|(mjvQ-m`1h`-Fs`Z_4p?QTz3h&x6mOf;3&O;V?r^Q%=*| zoRuwxsQC+6Ix}7J3dYya*;(=Vi!_7$NKP+!-nmsiGgI?C{Ntw+ zoSac&lV7etxQM-B+VgWw(%=rqi;m>mcbC_Z65!Z<9!w`6MC;#QY$yA; zV!YCX?|q9=SbWmpOXSSCDXu?$*l!@G;k*e`N5nymoLR#MY zWf2MrtAV(zKK%dI&6{u9*gS#~s-HVFIavzQ%M27p^(rNUzx(?mk%RYUEz6%wYZ|K0 zH0iya&;|`=Zmxfl>>H?#D6NNB~z zy98N8`dYHGSd&|A;8`sU2NEx=jRd4R8KXb?Spth18e}0BmWfx7M%8lL)HHGB?Q(Pb zU+@oMer&`2___&{a=joP)c|Y`*!IMYOShhrI0dMwVt2^2X5=pRD=t?| z)`sG}I2cm8*EGY0O z*Q|Q9fs8o9%nD~$zAA6ilkZQNK8yQqgB2&{(@XY#eb^Kjv*oMEO&OUeclS!2>fmba zy8t{~RFNi#_Z$GOf)pAL68X1hvAXd~RaArcfzbF;zW(G$T{rVgoK-j(iT$;8#}2*9 zQJ@?3DaK(cs_lEIsmt4ZKYh9h(rD1lj6qZI!L=7=m`nkP2Tm9VX#@7{n1X6%Q(7h~ z3yb9a`^5#UD+!{(R#E#28R<5LEfx{Q}w)-%-bTwA)Lh{sCeQ*@)Fj8@E2@KIdipB$(YH8nLQ;4Olop1e{( zecf^ppq@!82B|6nORlhAo>xSU!*ulM6{s967?iZmY@r|1_K@^v^4}|WM!fKQv{_g1lz+h z^;M;FK}U3J>&|;$(M{_6?Ywe3+C2<*V*yI2Y(fP=K{{=ur8_J@ zx>G_?u@EIhqyz+{r8^8nKw4OIcQ?|%`MA${fA1gPH^w){x5qhqpX1iWTF<)gE9Nz? zIs1&2Q~o#-75zB29GKDKprOw-)y=hu#hB{D@83$G$U6%6v7b6s0~kcho1N;#wmm~< zb#*&cs^wKxV{pYraE}|WQfoIIy?cy=*wGLv9w=Vrk_$CWB@pLgD*pa78%~xb8`ZB} zqC`v4l9 z*PN_B(4<`Ogm`W(Kvk5^EO;uhH#5wgoo6_7*F#Zt#c$reVBA%F5tzLyoC>s7==XVc zxNW#3s;6B8ltsfkMi&(=d&AJM{&!`%uM2a(S`L(Ue)G%z3+9zJ1 zpitES%!Uye)^@b85vDF|5>B`_M0q;`wH759GBDliFZZ5nHV9;86N*3|o&<>TG(UgS zcrXy$L})mvQ&Rfx+Oy|3@UR5yDuGhdUr@82$JZDCp*Zg2$2;2Al{`t-bfbVL!5pYA zyTf%4I!3tz?DIRXE9{Rf5jadSS92oHP&sf>mXcJ9Ls~QuK`w9Ar%Ph_%V%l6lemU`5m@CcQPs_M#{&mU|vNgkn1Xv-!n6eKqVBe zTzRy_=TOyo;3?6F_O4tBlmtR3-^5 z%FwLPciA)F!`({aJy;q)J2cYP zsP*qRQ^P53r83mDpiSIrSqboW>#=x<7W;SKdP|GO(w{$u9r-cbFx71b37xnHn5BLY znhXv{`;)n>1<2UUyP%+eS;8)_pkx_qKEQi5g0X|CDfRY_;p~76>zOltOo)?)7{H2E zrilZ*ubwu~ZN493oAh48y7KP;Z&9bQABAqpWh z+Z1cPUd9c^fJCuN7XJP{P09D~L&Wf8wz}v8Cd;_+sX_@vJ_PI+aeKa;lW66JF*uLj7w&(D)aZTo&6U{_DQLeOdkDxEca(r=gA zwL`%z7gs*Rp!!$?iDZn_J~KbxATYRR^m9voK>;N_eIkfbMr+Gwkd8-ZDw0vd<`X*) z*jbc8ML_^oJkSMGPu%MB5#wRJM-g;NEqV6d1Xhn?F*ZB9iN_vwxBvV1aVNuqqZ;B# zpD@8OFpy2V{l%fuuB-wD>)8DEst^&LUHmq7Rz zn7EHJ5Mo3q34NFVd0~#GQwM^OU#RF+h08U9kb?}CmjRS7vOzPyJSesi3l5{vbWaJ<{G(?+8`~Xijt%E5v)o}8 z2?c5Cm$=fFMDWE@V<5;x2(??Zordq?pjuR};RVzYMNpJH>3w-E5{29R)HjN(*dPD* z#_V~f|01nUKC+!RKE{~b;^5zLao=~Rgis^EL%7x&bkKWsx-@7Z7=rtELtg$3CfY!* zXuX>A?2~uxUIex$i4`?sS`%)anL$*2^a2VIX;mYgeKI8U%;_#Gb_6VdCZw{;7B+K~ zht<$BHT7gS{Mi z@7JOnsxn-G`9Mxk4#>H>lH=%^b(>mWG&gvhPrT{iiyDU}1Vdz-$8A~J+2yZZ%|UO9 zq?r8r^*Kl9m7j*(p$S$*huP)VW5KVasv7_Py%By|+^3-rn>IZ}JI~@pw>{y&@j8F$Ejl2 z#&Bc(KHj?wN3?*7c*o!)O3W^VQ6xZi^I9vaKJ*;IHx5`B-IK}IR8&m7?70g97qMMk zHNNV9K~5XTYmxGA-n47QJ4Qz2g3WqgL1hMC@BbUTI=TlK&1<4@0FUSj)-z;Ysb`u5 zLU!|F!AyC);9{G6hz3QCPqfO!F+rtIPoJ70d(7zFCBBWCjIG-}%MIu1!Y@C5{_L48 zL=R;e$v*5vg^fm>Xn0x|fXWzQb^;q|Wr#1ucoLHin9+etpUi}!SOzslQmE_lBr)}5 zdi-dMF*xWmv*+zK=!?(t*ly0yb#)o4aee&w>cI)3k-4ya$DTbt-{h0QvW$0LMu z3}7%9e^f}!c=87xYN9kpwJcFbOw(V!d?_1$6B}hd(Rs%L{OIJd)Q8lp)yh%mkbwW1 z#59nlm!$A1oex?w{I@)&KLv>eES?KmeN@AD7?SCv3Vwsd`~SyEcYUREqmiVW91sv7 z4UL&NkyV@SlMJdYaUi5>g--u z$C5W7VD#VemqRoGDV=~LoXQjwTK z9{d&=LBBc_CA~f|u{`-Z6x+$i8+6xas2fPFD1pL}0f)mj?yGRqOv^ zvDz6JwqukNKZjAoX@>Bakj7yL+%fH>y)j9V7tJB%ed*HIyWBI?f8nShLtHCp zH6W(E`8~Jyv(P5cBZ4!}P*v<)Y+oCRPoDchYd(aRYxFy<$Rq((fuN-9p6B}BIe&Um zxM*ZFQf@s?Dq42}RKzO)5R(dIlW`|tliXmmg;m+36$*)ifP7X8ejUP_v)ou^lc=-r zT)Rlpvi5?QwiJ?E6aj@%acF(=Jhtph6!;34-Gzw^8!FP8A*t$vqM2xl{zX;^+!lmr zVmAHL#BAumD)#-1!N6bsc6|K<=9Zb$<=slN6>iu05pI?I5Z8h{S&2L5UaxCm@o8aV zP5$Q1H)b!41yk>Cma-%JuvOPJN9E?t?p$a%X}3bkl*h7XQqEx_!?*}chTB@*Nkon7 zNF(fE5t#ygexjhQ5*VZ-s!yyB`Fx}h{c{0w2$E8HRXjgTct@Ymn$>{plLX=fY2oQp zi!6&Q%oT|4nJA2jI(T?^cxHN9UZrvQkZThE(tBrvKSK-Ul0k^+>IHwHiV#Hf@=mcE z{{FlYr5oCb+JlCRZ^$gR@mq9#0Kf4LSB_g(x8d$5hb*VM9@*BQ z2pSoo(YP|!o`-q-POlMZNuy8b;X;y3OBdGO&|JwXHv2CZpoO<-{BL=NM{Korl;7e5 z0*QZESm(gt6GdH|+SOGWH(lHOs-+!u!ycoXKP3Kf?*08^bTgUZF9^0YB&D3Mi6AG_ z*iUO*3yY*y!xhMO2H5XfK1)W`^;X~S=&veHu3!a{vKmykEfCDo+H z_4*8+it4jnj|Tc$A_PLF)3g+<)WGHj^rNDu_w?&G7sJH*t=#!LmEuQ6So;Sj<*#3V z_x0;PBHC1B#U79$RMIuK7ct{#GBxk2DB4H%KUlDTP!O90jfhkFHE&T>RP}k-R!#!d zN-IFyE)cb#M({~dQCXk#`%AlAAaf@3N%gt`*!aPmW@H_f}(2cwkJPLcq{I39dOF1t5uHHPYc_$`EsAd?+Sf3 zV^Unr6H=tXUq2&6w~vx)AT}vUg_F|~{jP6w zn`QjN+8h+vzx2~E*E@XZPz-|icxTv2Pmcx?nME|pvykNta&R>MH=3N~A74t0Fh3Fl z_bOH3$dR?5;^J6InI$iDfBP^WCHPB3@l3S-ND+0%H~w5mo5endB3c0Nw`bktW(PMe zqn*)?;=rLii(t# zwVd+Ek+$ewHrDdH+)mRP+}%ya#%cbiPkmZyKV^{z#Nvggk9 z3>P{Rg{UZTo2d`Vcz&TkbuDPPnBKEjNs4>fwI+lnZT&CiY#|p=8~(qVke2Yl`^Xh@ z_?X5h7tj-q*W>_b@Gh@tjX^j`t1Lyyiz+uBlMLK71q+K-*YJe6xH@mKfm2LON?4FJ z6%`W{zjrU?AI94nB89P`dEy(+bEEnB+9M64-_5Dil$9Agzgha2HQDK-67j1YY8Wxr zR8~Ii85v57prlDkOlcUW$uWNRi`;gVDB~$!cs%MabOawU82o9LWsHXOB)2{A zOdBZNdmR_k!Oq$nCexO53EaxsxnX;oD@*QD23ra;G8$$U7W`|kQ`A*qS+}pZH@>CC zD6o<}c{M&U@vS#S@>S!bUfUd`92kz~ejD7XQ70eoIBq8-A|Vur zS`u}Xw@?ytIQ}{r9#QX!UmLSqu`IPTtv#TzlBT7o7&&DT=6mCSFvc|EJUpdt*0=>u zBR`e%O8@eR$LrKL_`g)|*>*X8)6yYFcEE&a&Z3?^-65fX2AnD9SXh$mj|`E_DY3Y;)a8 zvS%Y42#DJ;lo_i&tw& zx$PXeb}cdh=W=w!d%4}dlUVHm=Ocj01rYW~E1!ILIK%Q-S~W2VC#Aq^T}eVBrS(3G zZx)IX8^GZx09nt^T6-O}wiMTXs3@zW6UuAe@ev=;v_+}EMMqgV_WO72k1=N$9m^}w z!T(64fp7qqnHON?<5RVB4q*a*c?pe9+^5euUZ{SQrKP2Vj0}Ot z2K9rgX*2YhsuXy%;NIh+S{)sG*_5#HL7aIBpdCu!T%ZGAAAQ#F9%S5K4UegLH%`CD zreB3wR$eG!sY9@)_R=<5iNu5++P(7p`SZDeBH@JZ-=BoF5=$cX?Y8!LmpjlY4PoU< zTwcBwnT^_ZeW^$RwG_q<5UV*O0jh^@rAoIT%&X-HT#8%O(C`z6so%wR;yupST&5VR zc3XdeVz9+#41&ct!;uFV6=btty}F1&)(}4d2z24uK2@+=aPp$DO~MYOU(iY>OXJOH;^23fHm9oNT*oCQ z)`D9DvthpZ;d*gEI}ptH5G;FISXfIyK!^u8S3^Uy@(n#@D25H{?57Z-5q^aqjXjZc z*EN#QM-))XI81OX`Upi^m91}Z80V>zmg8gyEHt%bqnfRT0WCzIg6`-_8a81TcaEoP73Avq++81+akG;N5q^f7J$@U zeOC@_VDCL9oUPs68mAogDKoRtGzfFh$JDRh6cvRbsX;x8Og(XFWg1Jqhq+&cj|PivsB7GYZ7gRvZ{90(A2uwcjFu!lF!zsa*tm|NWjz zT7GbF$Sw-+8fY)FOJE$~>F=ASc;LWbrehLbGZqZ3PoE4We3FyZaqVf&b(vro99>t( znA`PmH=cU~m<|~r;Osrh1w4c3*cza=1^&Eq?p$33lLYz;%e>7U7*DYY<#juM%5Q^g zt1tM0iX>N$FCQ>5P*C_rYmfPQ4!zs@(x5TsK;YPzDQkionfnicV_7I%5f_h5;*jSJ zk^yJoEeI_4@4uhmQP=6%{|l4iPx<-MB_-`Pjp}PenTk2Yr%$K)`}zzK0DNe^68@c- zH%3FK73iQiXwoQ#zzGTP_Etyfrhw~3d9>MLa3=D>Ov=b8ed363a|0zMWzMGd$XDYr zV}pY+sBSUAEmUT>gTV>p@5VFP#l&<8;9_HSH_c-sz}8-yx>3Ob0Y)0hgMO9V8;r4C zT?^yl<1@_K1#u$Oy1Vx#-&R)6z_mDh?3iQuBYO<0HHy}aF}?ypChQvz6nPMWPV@3M zQbrt~Tt24VuYt8Qk1r>XK#}qM>xXSLD_6k7f{&e?!sRAfO3GM#eKhCv+@U*X(e|E# zUXZEm!>3O_RYb%=cq5`MMwysO`Mtd6QMkmSiO)rRha}^h+%%Y($9(;|2}?FgKIzae z$H9^T3FQXHQp8F{L{*XRK6)j?6~H}sQ8^S}dJ@*UHltvaIeqU=uHRQES!HMLWo z-(nwbieFt_b#v<27U-6nrfxX2W%|USjWyK|lZKj-Mr>h>g=}1-}PkCbp$?7rL^z=@RBG(X*xv?T$<)3VR`NG)bWHOkpqv#Km z&{R_%IuwanmUK!A6fetNG37Gj2v)l9}4$mSo)`JF%kj z@^XFE{LJ*pJNU}XQ3q0sYDH|)!qFD5N^7$YLfBGN)-l-zv%O7a*(_9(~|QGXg5{D1CA6#&R+vqmq)+M_4|w3FZc2B8wls3rJrhtyznVQI>~KqPtL_NjFl;CYhU)RiHm#UJ)ntk5RK?HxVt4FLEziKX#5It z8OWAt;IaJ9GLL}9O}h1P6yQ&sDa2YKnRqS`Z{itx-GH`WhIVA zB^Rx07=(%3=;&ZUJ8Mrgz6dPsDhD%5u<(j#QhTZidZ@l1pDb*Nd5Ca@9Y4NZm=dvS z>#nSWYP*Rw&4tmnla}dR{ z>ZBTqR}8`5e3`O7G1A{ZuP8P^Z^nKM?=!=G@)*$h@>?km!d>In*VkQ%p;SVGU%Qzq z$lHhnz@J$?BfFnysTk`-+U>?{ob_xLnpuWD-rke3I4lx-Nv<2~o3f@Eue~%;76DZR zie)NzU&IhQAz|L@2Pklcy+8KiW@O=cp`3Fi$cZ4_6SObMu3o*0X_N*7L-;bm zg|6gNXJr?O2++|;SYO+I3Jgt9izod8vg87^7icBwtgF}RZTDeYd^BZ-amhNC*-%m6Y7cV|A8>c}*3^_r}Qx|x%jG@r{xiQ&%NB*lPmr+BaiKsnI zyGvqkd<_a82xlilIYBk-c05mKqU~kl0ca(AfJU9bC{AORYd4V-nc+Cg;sVu38qR-8 zGDb9v3`^uuSedm)P##;iZnB0e`!&A9@qk3MwL@TM{=s#vO2Nu1wKeDbc`@^J);~5W z=AAmk#s%nN5U~FZsU6Te!l6(RubFiOb6UZT`-}crxJKxR@;dmz4ox#Mit8UWev53- zTK)bb%Zd&k^6@p4S8=hi@<{AVu^)JxhWRxh-&LP+zW~hzSo5$5i45&fM6-aVDPp zqk3u0c)|PTC?8bM>bSWTsXX4$o*w)Idkp)6aND^`?@01HSFSijTBHi-=&-a~RhT-> zl$|7|yip&y6UaDDeI9AI4=|cDT%1gk;>fuIfwS6}u%x=Zd~F{Q7%zgB10&LPIThnV zDvtXq&^yL(+*&A!C-LYj|KK(`*w|f$*ICXW2Z;m(2q@fBP*rS7C{nD5y1iD5)6&)p0ySn5Sz(lguO6}u8tYm5fH;s!Jpm1+9`;;j)nfvl{urt@R;iPg-wrMOVcnhFqAR*o-Pu5qIIP1 zz=N(?*8&G-YkZ7QX9E_7YT-oz{j_I8Lq`CXU6+$nq-r6@nrmru^J8qn7w3|J3Qd9U z0_I5&=)L5)q>gM2p)g2$gna&Nao3H4f`Zw72o6qHu57_@NN=bnoO*pq_08*=qRWHB zBO{VvBp#%z8=aTDF?21*D=Q)4B}CbOc%^MKqZuvX-DYKNWi>TFU((Q^ywfJbme%UB z#{*;;1s$DhMXoy$-cFJ0_?N$*b{P46x~|TS%kT!gjyV3T*oR9|i=hmGUdy@A&`|e` zXtRr7_HCmmJdz+{H+IC)F@~(h=rZC=^yeDh%^4}8=GZ`0*wv@6#}!yJybJ%%?;zFQ zy?dcwWZ6|rjw}FC1tVUy{)vgI!1GaLa})G(SFZ{fWzes$KNxGxqE6)fD6#Z1^HYP- zZ=?Cg6ygbi6JFKx{a-YNgm{p+FydpI9KE)_zApLfNzD!8ot_9FC^b0lm}rL8|2TLk z0N{%m=So^!-1C+enyy>doE#l{Zy6Vk@0zlEvN#?F>gnkp(uTkOvkHD21m@O}Ot zavg?8`!8u(I~9Z`B&^wtQtkcldtYLFeD6>#;~pBn>rg{N{QXv0NuSXoTUK?3m9^(r zph8dYS^YY7^A)=vceo-|;sxB+v2et*(s+j}TqU0Tv)V7~NjQ3VtD zLR4DEUD7cMI^BYc$;&h0eaSBQ&T%o5H#i5?p|NlcITj`I;?nLzg{A_6XV?} zUJeD4ik?<-vgvGwWzYAW*o}p^w@#MSd2`5|LA_V+`_nfv3xun((8>`ABuZNFoI3S% zZjKxFnG!ZO(w-i90fNv)L2ZCT#>&m{8&c>x-+wHm2TI{$P6B&GpQV#nVPz@I3W$o;h}b+!ZJ~WC&|jH zC)+mT!bqM_iJboEym;*UcNWP#GKk?}lqLJvVZdE}OY*9-Ry%EL2rb0(_i@^dU< zVFJ$Q*?af$AOpw95H5xX!|U>X_m$ob+1a4B z%nmxdG{meRJ(O_|_+(7#3?0-ys5fQS^0vZ<-hWXQ;#hj@Vh0Z&epzNOr}4*`d$ZE#Zm}4enz9oTUl9>s2Qmz~0tGC4UIAC zP3m;>XT#behp`kfZOhku_;^Q;-g|l6jT(!8So-em>LQF`%c`obC6i`zCeQtGs zd)|SaYBy+L3?AE<575%KCf&};x^h{i(G?^9uKs|Hq%$3XZ{A$H8UBiVbAoMjbx3@1 zeOj+=Bdte1->nb2I~X3lCQIIr>z?!sHOAbs22ik}x~ScljFx8t4?vBAnTLs0UZUjV z)K3)LVPAGP`8iowTSp>jt*&nB>0P;H5Ytl=?(w~3{zrTJ-pJbPS4;ZY68VVA{_^E- zlm;^$PiZ_Qj|vWjnooyubs2r$LHZ0(lql z5_EJ4T3{av?b-J2@fjB(v=*l2?2udNf&C8rWa4KhKhe&+?0N0$D`R8xGWA_cT6L9T z3r$vlzyIlromXG1UzL^REi6=B2$hwj`GscrilN~V=)>J?%eJHww0RmT()*5g{37n0 ziRjZ$@%50*KF!LO*xZ5;4~kIvrI!;EX5;&&Mr;HX6jk~1#_RTU0M`P;n-5B(y@Ljc zv(DgA05v*<$toNkzpA-~_cbH5atBlJ^}q2eO9L|K|1U4{bB;0Oe3f0y(-dGONRJ>eMHR zyu7?p%B>DUn-h7reBL%hleUWf9Bv6wkemA$HNLFAiN>JH&uWgC_2_A`H2_4^Vs4+<1a770p!$pqE3FPVK%7O`cndD_*x92rAHM^s(r|#IflYxch33#Iz z1OF^5V-a01H(NS;`ZScySq~oC&i17Z<-bMO1*-o3yE0VCTtV!}({oNDz(P?%)D&%8 zz|pysOkyMN0A(^`^bhp+gM-KPvp`6OTmUY3PS1RQf%N&$mic4Y@lILR;>H zhY35vjPG`Nuj|@De&>Zf2Gtr;_St!P;k6DuBO~QKB~pSmCUSBV0Cn(9qHR$uq}Z{; zWG3xHe*R16$q-50;orY`U>F5qvc7%v#NExVjg1J&c&lM8lGBhoDiS{NgxfTB5 zM8MCVVJc#uBO>;A{TMyz#n7Un?zqo8r{!7j>6Hb!894A}^#rkR@W z)=s%KX!nB8LKt*z!_2ND9jAuwV~UQ|k=@%rHl-9S9O`vo!oxL#xR--VH5xZJy| zrRj^yI>Xk0L|Z=oFtj%1iws+7(V3Xh$n6P;a!F>OWc8=lPdh4<7oFi3bUSgnZN`(+ z)RdYO+H7(yD)sWiJR*>@?3~)gAXxBrQ|WDFB|8bh5%PGfh`i9Kfi1+Uc|E=F+{ z-N}1T!vYHmL@+kgw>)oY3)02iH*t-)BaR$`p9)A)Nr~AsEh{>9R#uRf?ixFD{B;LG zMpvNKAr78KpIh9er$IpV{{c(-1T*v2kSdMa$j}AfcpNE?3ID_blUlw5CzP$>$isf+ zs%<~011zGV9nt29G=zaw=_~q@dc|+(HM2nn2zm*}@32(sL5{KUhL>~#sU^3Q)zjVs zlUGzwke=+AmJSmQad&s;9bBC!(JuYzjXI-~e+0vksDg-yhghPWE#7?kahQ_wAT=on z70DswTGN)B&N2KuCx-B6-DR ze$c!5CEJ{idL&;<-+P?}VwZN*mKkPf5Q=ZmI>smTPRJT0#T8EckThEe~6?HnoaaUoq~~(6mKuFXV#03Zu1!jXXi8s3cWqM z5m#mjulJw6a_fQU4xo+*53mO5_uOw_ZkHu62>2IrV1#BdEaQ@Of_+>#ssj zcT==%fj4A!TC}p3mj&-8Y+(0cb=uooUQtm7#TDof245dZz=pAf&YYBV{2eqHvH1N? znnlO)E;&}Y?#>p(CM_zVxNW<`M0s(CWqqAdhHB!3 znTd(qF;@o`GV1|hVhw^Y3kN-6Qv$jA_U+rT{`&0N?KQa-u-Y6Um+}tk+gL(JkvfYy zeHK&HH$Gf@-61n?1v+3e9oxy1o}hmOFiX8X2V+<={pxi_3=*lah~9(!AY$^{Or#Qz7u2u@pP3+4{iN4HmRtaS<(JFN^sd73a|@$236n?#z%Aibx@ zinFy3lDKzKBtT1$${payTXxMSUv6}c1tY_Q;wa^?JiO5x?is!LhN@~Qxcus$^~ebg zm%2qPl|nPmzWkxJ)Z5hnaH4bp?{yCkH;?4JFs`Vo+6M!-kEzQ!;=HjcHlwRMu_m#mhQvT{GtT~ljTNF_TS zv(2MBh(uR}+MGtu^*h5gaCuR#Yi{^{G0hQNEJg}Ze(jwTn_eCl3!R#>z{1GhV&ExW zVPR(%JKe(S2(?t~N43xy1JZ+pUegwJ?0y7t-Q9&q>z+aP9oo`&XD1OfRF>u5a|goQ zSW!!B%LPlz0~k-;tYb2k=|SfM7sH=eHUFIIt&ynz<7MX!1%(dGP4U|6Ll`A675w+yL!5&wl+Q0i>S-wSE;F0!8{eFHU+=!8>)z&o<_UD-F+?3 z*=(67@0y#B(x377A9Vc@_{=yF{fK^=#HK~WZ&xaxFX+I=yGD#?yVA4lZ=@>Q3etnv z87t--3)mn2qvRKKI__P%bSdc06gsXf$KU|__wXx6!}~tu1-v3|J!sJ=kjc| zrnkHMOSykMtW!2h@z3e0DLtsAQopj?<&FhnZs(WvF|!b8&bCOBp?)05H@N}tBLlVU zDN5q{Wwmj=0|PoE`?CgqCLo@m-=9r{OHq+7&!@e8l`Z_PO)ag)kee3|V!f?h1QHUL zl9LNwN3pPZ=$=k%zT{GH>~D1>?zw1hJ^LYgAYYieGTXtlGCR+H)r>4BGlJ1|#983P z1u2PVubw|ob8uR2T75+wf-zZiTpV3m^P{4ThMY8MBIyKgLDKIz31-pO57E)NWtkw^ z<>x2t4#7^0g1UP1M>*S!aaS6zlbB>AXl5n(-(LRgFzu$%W@c_)4etcCB3F7~$s5E! zQNJr~N(c>Yl>L=x2huTi4p6Sl3(4ZG6MYwGO-j za_%D|v(%YV?73CaQ3~A?Nf(oo!*g>Fii;ayCtW_i;gizAEygcOZhg7Kb(5P{@7!;A zaaxr`ktI|=KI!B#{&?`~PG@IN-7#y+=@uH!BO?}8RzFIjdcW|#HfC$FeAk2%y*0)cB$7 zsA^RAFyrM{&}ReB4@!^$D_KIE`dJ}#6*66Qlc+7zjwZ{6IUsCYvqLN$>ww1uCi41e z=Em>~_=;`G<}CB$NYK3?G|6WI^o>-ARm-zWlnLp87_EY`atVZ&H20{fouT47e|~y? zJ_^KT>0o|n=em_3qyJeR^{U(k`wZta?4{cXhR7Txq==#AoOoyVi>k_!lD#KSQtx>p zxaWxzq8`dnyRqmkGZ)%fY;7Ysk@I~i&1Fq?(2ij{cZ+^0}9q?a=ur~ zZpufdeFioMaoJx(W)os*tp%Nt-c`3I+KTER3rr~3%gZ0YsFDu-XPbSe64^w7{Vwx@ zc@|Wr{K@&LWNsT|kg9gUsNl}|MtHQrVbB&bNnhfV*L|CsjuD{*k|Dmq!f_41+NHpw zIY>=iifuM=EiJl~l$7#J5O-MQLVtB`tlQJkjU5$Pmc;{fM2JsO`von2_0wJ!0+F>p zkFQT{$8gdSpe!t)0h9$2N~|A0e%D`239Y9UULJ~E?LEG60y66JqoiqkqH|E8D7%*X z4D#RIV`p~Dx9^|{+ifs7D&iaDt)*$n-rOpr^>*zZIg|0~59Vrb0^*UwBY7&z&cw7O zQKjPP0Y(k2E~%J$^4IU0?oUlCI291~hI39XK`v)OqGo#jT=EZg392BA$VZ0F;XkOs z&yy*mdK+4ZN(q&KvzTyI?6unp|vvsw&Lu#@g^KzkGE9TtjL4Gq=O0%Oq_ z`ks{Q!TQSBR}-%@RD?ynpTGZsLx((OtNmC(rI3X?I2fL&w6dIwFquwGvj#*GF7Dl= z;_;RE6PT?45JGkNEXJUeT5y^9Z})ZfbNkxa0`2_i6{#YPFi)+27=v_w$`Ktofxk9@ ztSfW|ND!Ar-|tC-`~H3;mS$o|9M5?Z9E$K_%9;(KQ9vE zM}*=3{&_S&zCQm#NdJ8i8wH{x`k&wb|L09;*{Z9rz+a1~lle}-7wGQY{`t^rhk#4a ziQfNQGS19gf(N@XHd`}l49l%Pxnp1@odJ|&O{vfH_YIlZERdWx5pO4Z37`sDhK5&> z+Xc@BA;+05%*shirlQ90P1t;>jg3_3fwa^9GbfCa{s=C{UX_i zh=}01Ic>tTLZS#bH&(jwwVr|mMrNfYDOrx0H}mA1H`+qNG3Zo*WDJCRx_XARmuS62 zJlnNPHnN`bb%6bIESWsnSCH7unVPzgdb^Yt?bL&P#|abwm6qtgPyBl|EBtx9Xi1qZ z2H&5`!&lFGLTjs_HaQunHcBd?j3-XiL{H*okxk9aY$`V41h$dZoas25^+}2K35A^5h6Hafp6$$xET`-0qcCn+gEt{Ae#u2T z=JnCFhEvniC2%DGi>s}z4Rs*_B7RU<#*UEPWYq_QYJTP+V{V$}BDb@!(Te!^@m)fK z3lKi?gk-NL+dK|-wWr?`!JwHwbhaius}@EjSdP7T_3BnuN{Cl)c84P{N-=2(i33P9 z48p<>!RA<)s8o8@>cgSEs-9=Z12(&Xr|A7piHZF+;hUjD;tlE08`|137*N3o>@p@d z76_E`IbBN06=J*5pI4thwaYz!m% zT8TWBcxFz{X~AFDpXx^AtC5s^4h3jhV1k2l!@|%>ekZcBGpG>yDM!i4AE2afixy$H zNw#z6W-?Ba|$OAqx6F);LQ$o@dQ;u z@&6sP5i>TvYu->+mbiCsTJBiPc}shHgC8#gRrB5M-!IzzMb~)0{lVzSmw3P`~q`QEP2G?3eN@1D>zukn(fZz4a%#xn5O zQpU&)avJ?MWL{ac+Ps|wxWq5}PSdZIl?7#lgF>$ zc>Oj}v*;vqKLc=1&8AiwCON5A35(B}WlQ8}yg`kY&b57Uk97a<6}&Qd0x{)EOn{Hi zCbiAEUN(aCf+72mb5LlQX4LA4+o+Q~b2?dt3G4$z4@ z`dl~nyn&>8fm6ynukk>F@y zym9m90n*LPp5g~Cyhrm%G_#;JGVAK*L%I_Rot;6i)y^t~M}D=aosyZ&?50{@;h z4JRi-!H`!duY(pS*;G)y-a@q?Eh$;Pm%h)`&`=MlZ*{`H$l#BKu}BGAhp}h%6S|OR zSJx7oO;Gv5y%4v4>Ev<6C_U@lmNVxR@17+JLqQFL(F5*T<7 z`z`wq-l~ki2GHgc0P6tMd+H>YmXvID2dxxE?aqCf>-mOf=+Qa7Y&QAl#EIABo419l z=&qjqJy6-%Gd%pP$PEQb-i}>$Ru$}*gF>ncU7YzHXZRV#JCg3a7_nKR6SDII;4rmF zfgzDve}TG!!uN%7&79dP^wGzoKHu;xDA?Sdw`i!)nURzP_EY_7j?Bh$`}Q?rwtH}4 zA@f1W*jQxWKKY^9rD7oY7gW=3U{D zyndwkHA5DwcXjY-`2ph;wHA?m#ej;MQv37tv-Z;X{Whx6NhT?(t4mzIyqS17VC>0) z6_YdHc%ZM3E^XM@z@XHf{MjQ<@ec|ag*wv+od__@jJE?S9eG7u+2PEYvUDPX5w~E+ zzDAf{^ z^{9JHsMGT(Df3^_%4yBgaHJvHlNMIiDj0n|_;MpT-HR^p*UvX%i7Z1=I&N$8@w{*M z^TibxpTJT4SuN%w;l9XCn}F@Ac_`HmF;&eGQ}}C_U9$- zuspzBmVD-YZ99d&yryRBNa5qhTY>Y2D`+R|raOAHBvd4jcWv9A>wsn7y?%W|CE<@x znQu%wzrJ=zXipDB{XKq`w}^KZ?gY%vHylG6RZr=WqM_O2;E+y##XR&mMhXNC!F8R% zCU+B9?l=rl>FHa1%YNoqQ;v0nJP6aJ#+BpveQhCQ>GQuekd5q&m>|P<8R+@F!JU5X z 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。Workflow 不创建 Tag。 -5. 检查 Draft Release 的文件、校验值、Release Notes、GPU 摘要和已知问题。确认无误后在 GitHub 页面点击 Publish;此时 GitHub 才创建 Tag。 +CI 和 CD 分开:PR 只做快速质量检查,`main` 做发布前健康检查,Release 测试并发布同一个候选产物。 -版本参数只接受 `X.Y.Z`。同版本同 commit 的 Draft 可更新;同名 Tag 指向其他 commit 时必须停止。发布前不要把 Token、`gpu-acceptance.json` 外的本机日志或认证文件上传到 artifact。 +## PR 和 main + +- PR 只运行 `CI / Quality`:依赖安装、类型检查、Lint、格式检查、测试、fake RPC smoke 和生产构建。 +- 合并到 `main` 后,额外运行真实 Runtime/RPC、x64 AppImage/deb 构建,以及 Ubuntu 22.04 X11 和 Ubuntu 24.04 Wayland 两组安装包 smoke。 +- PR 不下载真实 Runtime、不打包、不运行 GPU 或显示矩阵。 + +## Release + +1. 确认目标 commit 已在 `main`,并在本机原生 Wayland + RTX 3090 完成 [人工发布验收](release-acceptance.md),生成 `~/.local/state/omp-desktop/release-acceptance/.json`。 +2. 在 GitHub Actions 手动运行 `Release`,输入不带 `v` 的版本,例如 `0.1.1`。 +3. `Build release candidate` 在 Hosted Runner 上只构建一次 AppImage、deb、SHA-256 和构建指标,并上传为 artifact。 +4. 四组 Hosted 测试(Ubuntu 22.04/24.04 × X11/Wayland)都下载并测试这个 artifact;测试安装后的 `.deb`,不重新构建。 +5. `RTX 3090 Wayland candidate acceptance` 使用标签 `[self-hosted, Linux, X64, rtx3090, wayland]`,下载同一个 AppImage,检查真实 GPU、WebGL/WebGL2、窗口、截图和 RPC。不在真机重新打包。 +6. 全部通过后,Workflow 创建 Draft Release `v` 并上传同一批文件。人工检查产物、SHA-256、截图和 GPU 证据,在 GitHub 页面点击 **Publish**。 + +版本参数只接受 `X.Y.Z`。已有正式 Tag 时 Workflow 会停止,避免覆盖。发布 artifact 不得包含 Token、认证文件或本机日志。 diff --git a/scripts/ci-linux-display-smoke.sh b/scripts/ci-linux-display-smoke.sh index 73e5331..b1cc540 100755 --- a/scripts/ci-linux-display-smoke.sh +++ b/scripts/ci-linux-display-smoke.sh @@ -3,10 +3,11 @@ set -euo pipefail display_server="${1:-}" +smoke_executable="${2:-${OMP_SMOKE_EXECUTABLE:-}}" case "$display_server" in x11 | wayland) ;; *) - echo "用法:$0 " >&2 + echo "用法:$0 [executable]" >&2 exit 2 ;; esac @@ -14,8 +15,10 @@ esac artifact_dir="${RUNNER_TEMP:-/tmp}/omp-ci" screenshot_path="$PWD/tests/artifacts/${display_server}-smoke.png" weston_pid="" +smoke_home="$artifact_dir/home" -mkdir -p "$artifact_dir" tests/artifacts +mkdir -p "$artifact_dir" tests/artifacts "$smoke_home" +export HOME="$smoke_home" cleanup() { local exit_code=$? @@ -30,7 +33,7 @@ cleanup() { cp "$app_log" "$artifact_dir/main.log" fi - pgrep -a -f '/electron/dist/electron' >"$artifact_dir/electron-processes-after.txt" || true + pgrep -a -f '(/electron/dist/electron|/omp-desktop)' >"$artifact_dir/electron-processes-after.txt" || true exit "$exit_code" } trap cleanup EXIT @@ -39,8 +42,12 @@ trap cleanup EXIT uname -a cat /etc/os-release printf 'node=%s\n' "$(node --version)" - printf 'pnpm=%s\n' "$(pnpm --version)" - printf 'electron=%s\n' "$(node -p "require('./node_modules/electron/package.json').version")" + printf 'pnpm=%s\n' "$(pnpm --version 2>/dev/null || echo packaged)" + if [[ -f node_modules/electron/package.json ]]; then + printf 'electron=%s\n' "$(node -p "require('./node_modules/electron/package.json').version")" + else + printf 'electron=packaged\n' + fi printf 'display=%s\n' "$display_server" } >"$artifact_dir/environment.txt" @@ -52,10 +59,13 @@ export XMODIFIERS=@im=ibus if [[ "$display_server" == "x11" ]]; then export XDG_SESSION_TYPE=x11 - xvfb-run \ - -a \ - --server-args='-screen 0 1440x900x24 -nolisten tcp' \ - pnpm smoke + smoke_command=(node scripts/electron-smoke.mjs) + if [[ -n "$smoke_executable" ]]; then + export OMP_SMOKE_EXECUTABLE="$smoke_executable" + else + smoke_command=(pnpm smoke) + fi + xvfb-run -a --server-args='-screen 0 1440x900x24 -nolisten tcp' "${smoke_command[@]}" else unset DISPLAY export XDG_SESSION_TYPE=wayland @@ -89,7 +99,12 @@ else exit 1 fi - pnpm smoke + if [[ -n "$smoke_executable" ]]; then + export OMP_SMOKE_EXECUTABLE="$smoke_executable" + node scripts/electron-smoke.mjs + else + pnpm smoke + fi fi if [[ ! -s "$screenshot_path" ]]; then @@ -105,9 +120,9 @@ if ! grep -F "backend: '$expected_input_backend'" "$app_log" >/dev/null; then exit 1 fi -if pgrep -f '/electron/dist/electron' >/dev/null; then +if pgrep -f '(/electron/dist/electron|/omp-desktop)' >/dev/null; then echo 'Smoke 结束后仍有 Electron 进程残留' >&2 - pgrep -a -f '/electron/dist/electron' >&2 || true + pgrep -a -f '(/electron/dist/electron|/omp-desktop)' >&2 || true exit 1 fi diff --git a/scripts/electron-smoke.mjs b/scripts/electron-smoke.mjs index 3b09a58..a0d553c 100644 --- a/scripts/electron-smoke.mjs +++ b/scripts/electron-smoke.mjs @@ -2,9 +2,11 @@ import { spawn } from 'node:child_process' import { access } from 'node:fs/promises' import { constants } from 'node:fs' import process from 'node:process' -import electronBinary from 'electron' - -await access('out/main/index.js', constants.R_OK) +const packagedExecutable = process.env.OMP_SMOKE_EXECUTABLE +const electronBinary = packagedExecutable + ? undefined + : (await import('electron')).default +if (!packagedExecutable) await access('out/main/index.js', constants.R_OK) const useXvfb = process.platform === 'linux' && !process.env.DISPLAY const displayServer = process.env.OMP_DISPLAY_SERVER @@ -28,25 +30,29 @@ const explicitElectronArgs = ? ['--ozone-platform=wayland'] : [] if (softwareRendering) explicitElectronArgs.push('--disable-gpu') +const entrypoint = packagedExecutable ? undefined : 'out/main/index.js' +const smokeArgs = entrypoint + ? [...explicitElectronArgs, entrypoint, '--smoke'] + : [...explicitElectronArgs, '--smoke'] const command = displayServer - ? electronBinary + ? (packagedExecutable ?? electronBinary) : useXvfb ? 'xvfb-run' - : electronBinary + : (packagedExecutable ?? electronBinary) const args = displayServer - ? [...explicitElectronArgs, 'out/main/index.js', '--smoke'] + ? smokeArgs : useXvfb ? [ '-a', - electronBinary, + packagedExecutable ?? electronBinary, '--ozone-platform=x11', - 'out/main/index.js', + ...(entrypoint ? [entrypoint] : []), '--smoke' ] - : ['out/main/index.js', '--smoke'] + : smokeArgs console.log( - `Electron smoke 环境:arch=${process.arch} display=${displayServer ?? (useXvfb ? 'x11-xvfb' : 'auto')} rendering=${softwareRendering ? 'software' : 'default'} shutdown=${terminateOnReady ? 'forced-after-ready' : 'normal'}` + `Electron smoke 环境:arch=${process.arch} display=${displayServer ?? (useXvfb ? 'x11-xvfb' : 'auto')} executable=${packagedExecutable ?? 'source'} rendering=${softwareRendering ? 'software' : 'default'} shutdown=${terminateOnReady ? 'forced-after-ready' : 'normal'}` ) const child = spawn(command, args, { diff --git a/src/main/index.ts b/src/main/index.ts index 6a4c263..a48593b 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -32,6 +32,7 @@ const setupProviderMode = process.argv.includes('--setup-provider') const supportedCliFlags = new Set([ '--version', '--disable-gpu', + '--no-sandbox', '--setup-provider', '--smoke' ])