Skip to content

Agent/tray UI and reconnect - #1

Merged
starsstreaming merged 3 commits into
mainfrom
agent/tray-ui-and-reconnect
Jul 30, 2026
Merged

Agent/tray UI and reconnect#1
starsstreaming merged 3 commits into
mainfrom
agent/tray-ui-and-reconnect

Conversation

@starsstreaming

@starsstreaming starsstreaming commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • 新功能

    • 新增 Windows 安装包,内置所需运行时,并支持开始菜单、桌面快捷方式及登录自动启动。
    • 新增安装包构建命令与完整的 Windows 安装、升级和卸载说明。
  • 改进

    • 托盘程序支持单实例运行,启动更稳定,图标与开关界面得到优化。
    • 检测到连接环境变化时可自动重连,减少会话中断。
  • 问题修复

    • 改进已运行实例检测及启动时序,避免重复启动和不必要的构建。
  • 测试

    • 增加连接身份变化后的自动重连验证。

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

新增 Windows 自包含安装包及其构建、安装和启动流程,更新托盘单实例与界面资源处理,并修复 CDP 浏览器身份变化后的会话重连。

Changes

Windows 安装包与托盘运行时

Layer / File(s) Summary
安装包定义与构建入口
README.md, docs/windows-installer.md, installer/windows/beauticode.iss, package.json, .gitignore
新增 Windows 安装器文档、Inno Setup 配置、构建命令及产物忽略规则。
运行时暂存与完整性校验
scripts/build-windows-installer.ps1
校验构建环境,下载并验证 Node.js,准备 staging 目录并复制运行时和构建产物。
构建清单与安装包输出
scripts/build-windows-installer.ps1, .github/workflows/ci.yml
生成 release manifest,验证暂存运行时和适配器导出,编译安装包并输出 SHA-256;CI 增加 PowerShell 语法检查。
安装包启动与托盘单实例控制
scripts/start-beauticode-engine.ps1, apps/tray/start-tray.ps1
通过互斥量避免重复启动,支持打包 Node.js 运行时和指定 Node 路径,并调整托盘与 Codex 启动顺序。
托盘开关与图标资源
apps/tray/start-tray.ps1
新增自绘开关控件,更新开关状态和配色,并从 PNG 生成托盘及头部图标。

CDP 身份变化后的会话恢复

Layer / File(s) Summary
身份变化重连与测试覆盖
packages/adapter-codex/src/session.ts, packages/adapter-codex/test/mock-cdp.js, packages/adapter-codex/test/adapter.test.js
CDP 身份不匹配时重建 host 并重新连接;mock CDP 支持浏览器身份轮换,测试覆盖 reapply 恢复流程。

Estimated code review effort: 5 (Critical) | ~90+ minutes

Sequence Diagram(s)

sequenceDiagram
  participant BuildScript
  participant InnoSetup
  participant Installer
  participant Tray
  participant Codex
  BuildScript->>InnoSetup: 构建安装包
  InnoSetup->>Installer: 安装打包运行时与应用文件
  Installer->>Tray: 安装完成后启动托盘
  Tray->>Codex: CDP 未发现时触发 Codex 启动
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题与主要改动一致,概括了托盘 UI 调整和重连逻辑。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/tray-ui-and-reconnect

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Windows installer, faster tray startup, single-instance lock, and CDP reconnect

✨ Enhancement 🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Adds a self-contained Windows installer (Inno Setup + pinned/verified Node.js runtime) with build
 script, release manifest, and docs.
• Hardens tray startup with a single-instance mutex, custom animated toggle control, app
 icon/branding, and bundled-runtime detection.
• Fixes CDP session reconnect so a Codex Desktop restart (browser identity change) triggers a clean
 host rebind instead of failing.
• Speeds up the engine launcher by spawning the tray before Codex/AppX lookup and replacing a
 process scan with a fast mutex check.
• Adds README v0.1 download link and usage docs; adds regression test + mock CDP support for
 identity rotation.
Diagram

graph TD
  A["start-beauticode-engine.ps1"] --> B{"Tray mutex held?"}
  B -->|No| C["start-tray.ps1"] --> D["session-host.mjs"] --> E["BeautiSession"]
  E --> F{"CDP identity changed?"}
  F -->|Yes| G["Rebind Host + Reconnect"] --> H["Codex Desktop CDP"]
  F -->|No| H
  B -->|Yes| I["Exit quietly"]
  J["build-windows-installer.ps1"] --> K["beauticode.iss (Inno Setup)"] --> L["beautiCode-Setup.exe"]
  C -.uses runtime from.-> L
  subgraph Legend
    direction LR
    _svc(["Process/Service"]) ~~~ _dec{"Decision"} ~~~ _ext[["External App"]]
  end
Loading
High-Level Assessment

The PR's approach is appropriate for the stated goals: a named OS mutex is the standard lightweight mechanism for single-instance enforcement on Windows (cheaper than process enumeration), Inno Setup with a pinned/checksum-verified Node.js download is a reasonable way to ship a self-contained installer without adopting a heavier packaging framework (e.g., pkg/nexe or Electron), and catching CdpIdentityMismatchError to rebind the CDP host directly addresses the real failure mode of a Codex restart. Alternatives like Electron-based packaging or a signed MSIX were considered implicitly out of scope given the unsigned SmartScreen note in the docs, and are reasonable to defer.

Files changed (12) +815 / -70

Enhancement (2) +294 / -58
start-tray.ps1Single-instance mutex, bundled runtime support, animated toggle control, and header icon +255/-33

Single-instance mutex, bundled runtime support, animated toggle control, and header icon

• Adds a named Mutex to prevent duplicate tray instances, supports a -NodePath parameter and bundled runtime\node.exe fallback, skips build when a release-manifest.json is present, validates required runtime files exist, replaces the button-based toggle switches with a custom-drawn BeautiCodeToggle control, and loads the app icon/header mark from the PNG asset with graceful fallback to the generated glyph.

apps/tray/start-tray.ps1

start-beauticode-engine.ps1Speed up launcher via mutex check and reordered Codex launch +39/-25

Speed up launcher via mutex check and reordered Codex launch

• Replaces the Win32_Process-based duplicate-instance scan with a fast named-mutex check, passes -SkipBuild to the tray when a release manifest exists, and reorders startup to spawn the tray before launching Codex so tray display is no longer blocked on Codex/AppX lookup.

scripts/start-beauticode-engine.ps1

Bug fix (1) +25 / -4
session.tsReconnect CDP host on Codex browser identity mismatch +25/-4

Reconnect CDP host on Codex browser identity mismatch

• Refactors ensureHost's connection logic into a reusable connectCurrentHost helper and catches CdpIdentityMismatchError to close the stale host, create a fresh one, and retry the connection when Codex restarts and rotates its Chromium browser identity.

packages/adapter-codex/src/session.ts

Tests (2) +45 / -2
adapter.test.jsAdd regression test for CDP identity-change reconnect +37/-0

Add regression test for CDP identity-change reconnect

• Adds a test verifying BeautiSession.reapply() successfully reconnects after the mock CDP server rotates its browser identity, simulating a Codex restart.

packages/adapter-codex/test/adapter.test.js

mock-cdp.jsSupport mutable browser identity in mock CDP server +8/-2

Support mutable browser identity in mock CDP server

• Converts browserId to a mutable value exposed via a getter and adds a rotateBrowserIdentity helper so tests can simulate a Codex restart changing the CDP browser identity.

packages/adapter-codex/test/mock-cdp.js

Documentation (2) +93 / -4
README.mdDocument Windows installer and add v0.1 download link +33/-4

Document Windows installer and add v0.1 download link

• Adds a v0.1 installer download section and a new 'Windows installer (recommended)' usage section, moving source-based setup instructions under a separate heading and documenting the installer:windows npm script.

README.md

windows-installer.mdAdd Windows installer documentation +60/-0

Add Windows installer documentation

• New document describing installer user experience, build prerequisites/steps, and release/signing boundaries including the unsigned SmartScreen warning and Inno Setup non-commercial license caveat.

docs/windows-installer.md

Other (5) +358 / -2
ci.ymlLint new installer build script in CI +2/-1

Lint new installer build script in CI

• Adds scripts/build-windows-installer.ps1 to the list of PowerShell scripts parsed for syntax errors in CI.

.github/workflows/ci.yml

.gitignoreIgnore generated installer artifacts +1/-0

Ignore generated installer artifacts

• Adds artifacts/ to gitignore to exclude installer build output and staging directories.

.gitignore

beauticode.issAdd Inno Setup installer script +58/-0

Add Inno Setup installer script

• New Inno Setup script defining a per-user installer with optional desktop/autostart shortcuts, a Start menu shortcut, and a post-install launch task, all invoking start-beauticode-engine.ps1.

installer/windows/beauticode.iss

package.jsonAdd installer:windows npm script +2/-1

Add installer:windows npm script

• Adds a new npm script that invokes scripts/build-windows-installer.ps1 to build the Windows installer.

package.json

build-windows-installer.ps1Add Windows installer build script +295/-0

Add Windows installer build script

• New script that builds the TypeScript workspaces, stages a minimal runtime directory, downloads and checksum-verifies the pinned Node.js Windows x64 runtime, generates an app icon and release manifest, probes the staged runtime, and compiles the Inno Setup installer, printing the final SHA-256 digest.

scripts/build-windows-installer.ps1

@starsstreaming
starsstreaming merged commit 9392ebb into main Jul 30, 2026
12 of 13 checks passed
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
scripts/start-beauticode-engine.ps1 (1)

101-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

注释与实际保护机制不符。

第 109 行注释 "Fail open: the session-host injector lock still rejects duplicate owners." 提到的 "session-host injector lock" 在代码库中并不存在。实际兜底保护是 apps/tray/start-tray.ps1 中托盘脚本自身创建的同名互斥量(Local\beautiCode.Engine.Tray.v1,初始持有权 $true),而非什么 "injector lock"。建议修正注释以准确描述真正的兜底机制,避免后续排查问题时产生误导。

📝 建议修正注释
   } catch {
-    # Fail open: the session-host injector lock still rejects duplicate owners.
+    # Fail open: apps/tray/start-tray.ps1 owns an authoritative named mutex
+    # ("Local\beautiCode.Engine.Tray.v1") and will exit immediately if a
+    # second instance tries to acquire it, so a false negative here is safe.
     return $false
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/start-beauticode-engine.ps1` around lines 101 - 116, Update the
fallback comment in Test-BcTrayRunningFast to accurately state that
apps/tray/start-tray.ps1 creates and initially owns the same
Local\beautiCode.Engine.Tray.v1 mutex, rather than referring to a nonexistent
session-host injector lock. Keep the mutex handling and fail-open behavior
unchanged.
apps/tray/start-tray.ps1 (1)

9-24: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

互斥量创建缺少异常保护。

脚本以隐藏窗口方式启动(由 start-beauticode-engine.ps1WindowStyle Hidden 拉起),而第 14-18 行 [System.Threading.Mutex]::new(...) 若抛出异常(例如极端情况下的权限/命名冲突),将导致整个托盘进程无提示崩溃退出,用户完全不会看到任何反馈。建议对该初始化做一次 try/catch 兜底(即使只是记录日志或回退为“继续启动”),避免静默失败。

🛡️ 建议的兜底处理
 $script:trayInstanceMutex = $null
 $script:trayInstanceMutexOwned = $false
 $createdNew = $false
-$script:trayInstanceMutex = [System.Threading.Mutex]::new(
-  $true,
-  "Local\beautiCode.Engine.Tray.v1",
-  [ref]$createdNew
-)
-if (-not $createdNew) {
-  $script:trayInstanceMutex.Dispose()
-  exit 0
+try {
+  $script:trayInstanceMutex = [System.Threading.Mutex]::new(
+    $true,
+    "Local\beautiCode.Engine.Tray.v1",
+    [ref]$createdNew
+  )
+  if (-not $createdNew) {
+    $script:trayInstanceMutex.Dispose()
+    exit 0
+  }
+} catch {
+  # Fail open: proceed without single-instance protection rather than a
+  # silent, unreported crash of a hidden-window process.
+  $script:trayInstanceMutex = $null
+  $createdNew = $true
 }
 $script:trayInstanceMutexOwned = $true
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/tray/start-tray.ps1` around lines 9 - 24, 在 start-tray.ps1 的
trayInstanceMutex 初始化流程中加入 try/catch 保护,覆盖 [System.Threading.Mutex]::new
调用及相关状态设置;捕获异常后提供可诊断的日志或明确的回退行为,避免隐藏窗口启动时因互斥量创建失败而静默崩溃,同时保持已创建实例的退出逻辑不变。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/adapter-codex/src/session.ts`:
- Around line 235-240: 同步更新 watchTick() 的身份不匹配恢复路径:重建 host 后清空
detachedVideoKey,再执行重发布,确保重启后的 Chromium 会重新附加本地视频;可抽取并复用 ensureHost()
的共享恢复逻辑。补充覆盖端口、会话数量和 generation 相同场景的视频重连测试。

In `@scripts/build-windows-installer.ps1`:
- Around line 246-247: Update the metadata logic around $commit and
$trackedChanges so installer builds continue when Git or the repository’s .git
metadata is unavailable. Detect whether Git metadata can be queried, use
conservative fallback values such as commit “unknown” and dirty true when it
cannot, and preserve the existing Git-derived values when available.

---

Nitpick comments:
In `@apps/tray/start-tray.ps1`:
- Around line 9-24: 在 start-tray.ps1 的 trayInstanceMutex 初始化流程中加入 try/catch
保护,覆盖 [System.Threading.Mutex]::new
调用及相关状态设置;捕获异常后提供可诊断的日志或明确的回退行为,避免隐藏窗口启动时因互斥量创建失败而静默崩溃,同时保持已创建实例的退出逻辑不变。

In `@scripts/start-beauticode-engine.ps1`:
- Around line 101-116: Update the fallback comment in Test-BcTrayRunningFast to
accurately state that apps/tray/start-tray.ps1 creates and initially owns the
same Local\beautiCode.Engine.Tray.v1 mutex, rather than referring to a
nonexistent session-host injector lock. Keep the mutex handling and fail-open
behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c5800226-768e-4e52-871d-baaf65af52a9

📥 Commits

Reviewing files that changed from the base of the PR and between 61ee234 and c3df8b9.

📒 Files selected for processing (12)
  • .github/workflows/ci.yml
  • .gitignore
  • README.md
  • apps/tray/start-tray.ps1
  • docs/windows-installer.md
  • installer/windows/beauticode.iss
  • package.json
  • packages/adapter-codex/src/session.ts
  • packages/adapter-codex/test/adapter.test.js
  • packages/adapter-codex/test/mock-cdp.js
  • scripts/build-windows-installer.ps1
  • scripts/start-beauticode-engine.ps1

Comment on lines +235 to +240
this.onStatus?.(`Codex CDP restarted on :${this.port}; reconnecting…`);
this.host?.close();
this.host = this.createHost(this.port);
this.detachedVideoKey = "";
this.lastPublishSessionKey = "";
await connectCurrentHost();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

同步更新 watch 重连路径的视频重建状态。

Line 238 只覆盖 ensureHost() 的恢复;watchTick() 的身份不匹配恢复会重建 host 后直接重发布,但未清空 detachedVideoKey。当端口、会话数量和 generation 恰好相同时,视频会被判定为无需强制重建,可能无法向重启后的 Chromium 重新附加本地视频。请抽取共享恢复逻辑,或在 watch 路径中同样清空该 key,并补充视频重连测试。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/adapter-codex/src/session.ts` around lines 235 - 240, 同步更新
watchTick() 的身份不匹配恢复路径:重建 host 后清空 detachedVideoKey,再执行重发布,确保重启后的 Chromium
会重新附加本地视频;可抽取并复用 ensureHost() 的共享恢复逻辑。补充覆盖端口、会话数量和 generation 相同场景的视频重连测试。

Comment on lines +246 to +247
$commit = (& git -C $RepoRoot rev-parse --short=12 HEAD).Trim()
$trackedChanges = @(& git -C $RepoRoot status --porcelain --untracked-files=no)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

不要让 Git 元数据阻断安装器构建。

第 246-247 行无条件依赖 git,但文档前置条件未包含 Git;从源码 ZIP 构建或未安装 Git 时会失败。请在 Git 或 .git 不可用时写入如 commit: "unknown"dirty: true 的保守值,或明确将 Git 加入前置条件。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/build-windows-installer.ps1` around lines 246 - 247, Update the
metadata logic around $commit and $trackedChanges so installer builds continue
when Git or the repository’s .git metadata is unavailable. Detect whether Git
metadata can be queried, use conservative fallback values such as commit
“unknown” and dirty true when it cannot, and preserve the existing Git-derived
values when available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant