Skip to content

feat(desktop): complete OpenWork Tauri parity - #82

Open
yiliang114 wants to merge 13 commits into
replatform/tauri-shellfrom
cx/openwork-tauri-pr2
Open

feat(desktop): complete OpenWork Tauri parity#82
yiliang114 wants to merge 13 commits into
replatform/tauri-shellfrom
cx/openwork-tauri-pr2

Conversation

@yiliang114

@yiliang114 yiliang114 commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

This is the second, stacked part of the OpenWork Tauri migration. It is based on #81 and closes the product gaps intentionally left after the foundational shell: OpenWork appearance and productivity controls, native browser/pet/menu integration, safe legacy-state migration, WhatsApp channel support, and signed cross-platform release packaging.

The Web Shell remains the only renderer and qwen serve remains the only agent runtime. Existing Qwen behavior for sessions, models, permissions, attachments, worktrees, skills, extensions, MCP, scheduled tasks, and channel lifecycle is reused instead of duplicated.

The desktop layer adds a command palette, thinking controls, persistent themes and accessibility preferences, localized OpenWork surfaces, a sandboxed browser dock for HTTP(S) links, validated session deep links, native completion notifications, Wake Lock handling, native menus, pet support, and bundled document tools.

Migration is first-launch, non-destructive, and idempotent. It imports active workspace and session data, archives unsupported legacy metadata with checksums, leaves credentials untouched, and rolls back only files that still match the migration report.

Telegram exposes management metadata and WhatsApp runs as a normal daemon channel with persisted auth state, pairing logs, transient reconnects, echo filtering, and text replies. Release automation produces updater metadata plus macOS DMG, Windows NSIS, and Linux AppImage/deb artifacts while requiring signing material for published builds.

Repository maintenance is now explicit as well: OpenWork tracks Qwen Code through a fetch-only upstream remote and normal merge commits, and active workflows are limited to an allowlist of six OpenWork-owned workflows. Qwen-specific Pages, scheduled E2E, bot, cache, stale, hygiene, asset-cleanup, audio-prebuild, and self-hosted runner workflows are removed with documented restore conditions. Retained CI routes OpenWork to hosted Windows and skips Qwen's model-backed merge-queue job because this repository does not own those runners or OPENAI_* credentials.

Why it's needed

#81 establishes the Tauri + Web Shell architecture and proves that OpenWork can start the bundled Qwen runtime and recover sessions. This follow-up makes that architecture product-complete without bringing back the Electron renderer, Electron IPC, a second agent runtime, or the old messaging gateway.

Keeping this as a stacked PR makes the review boundary explicit: review and merge #81 first, then retarget this PR to main after #81 lands.

Reviewer Test Plan

How to verify

  1. Launch the packaged desktop app, create and reopen a session, then use the command palette, thinking shortcut, composer controls, themes, zoom, transcript width, high contrast, and reduced motion. Confirm the selected preferences survive relaunch.
  2. Open an HTTP(S) link from chat and confirm it appears in the docked browser while session links remain in the authenticated app. Confirm invalid schemes and malformed session deep links are rejected, and that browser and pet actions work from the native menus.
  3. Start once with isolated legacy OpenWork data, confirm workspace/session data is imported without modifying the source, relaunch to confirm idempotence, then modify a migrated file and confirm rollback refuses to delete the changed file.
  4. Add WhatsApp and Telegram channels. Confirm WhatsApp does not report connected until pairing completes, transient disconnects reconnect, self echoes are ignored, and text replies flow through the normal channel lifecycle.
  5. Run a dry-run desktop release and confirm the expected platform bundles and updater metadata are selected; confirm a published build fails closed when required updater, macOS, or Windows signing material is absent.
  6. Confirm the workflow allowlist accepts the six retained workflows, OpenWork CI selects windows-2022, and the model-backed integration job is repository-gated to QwenLM/qwen-code. Follow the documented upstream merge procedure in a throwaway branch and confirm unreviewed workflows are removed before the first push.

Evidence (Before & After)

Before: #81 provides the runnable Tauri/Web Shell baseline, with its screenshots and E2E session report attached to that PR; the product-parity controls above are intentionally absent there.

After: the bundled runtime passes its health smoke, and an unsigned macOS ARM64 DMG was rebuilt from final commit ea125fc16f. The final blocker-fix pass covers 385 focused Web Shell tests, 80 daemon-worker tests, 41 Rust tests, 4 WhatsApp lifecycle tests, migration/release contracts, workflow allowlisting, actionlint, and runtime packaging. Broader build and typecheck results from the same branch were reused instead of rerun. No duplicate baseline screenshot is attached to this stacked PR.

Tested on

OS Status
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

Environment (optional)

macOS packaged Tauri application using the bundled Qwen runtime; focused checks ran with Node.js 22 and the repository Rust toolchain.

Risk & Scope

  • Main risk or tradeoff: Native URL ownership, migration, and release signing cross trust boundaries; these paths use exact runtime-origin checks, scheme/path validation, checksummed migration reports, and fail-closed signing requirements.
  • Not validated / out of scope: Windows and Linux packages were not launched locally. The local macOS DMG is unsigned and unnotarized; public releases fail closed until updater, Apple, and Windows signing secrets are configured. The legacy Electron renderer, IPC, agent runtime, updater, and messaging gateway are intentionally not restored.
  • Breaking changes / migration notes: No breaking change to the PR1 runtime contract. Legacy import is automatic on first launch, preserves source data and credentials, and records an auditable rollback report.

Linked Issues

Stacked on #81. Merge #81 first, then retarget this PR to main.

中文说明

本 PR 做了什么

这是 OpenWork Tauri 迁移的第二个堆叠 PR,基于 #81,补齐基础壳层刻意保留的产品差距:OpenWork 外观与效率控制、原生浏览器/桌宠/菜单集成、安全的旧状态迁移、WhatsApp 渠道支持,以及带签名的跨平台发布打包。

Web Shell 仍是唯一渲染层,qwen serve 仍是唯一 Agent 运行时。会话、模型、权限、附件、worktree、技能、扩展、MCP、定时任务和渠道生命周期均复用 Qwen 现有实现,不引入重复实现。

桌面层增加命令面板、思考强度控制、持久化主题和无障碍偏好、本地化 OpenWork 界面、用于 HTTP(S) 链接的沙箱化停靠浏览器、经过校验的会话深链、原生完成通知、Wake Lock、原生菜单、桌宠支持和内置文档工具。

迁移仅在首次启动执行,非破坏且幂等。它导入活动工作区和会话数据,以校验和归档无法直接迁移的旧元数据,不触碰凭据,并且只回滚仍与迁移报告一致的文件。

Telegram 增加可管理元数据;WhatsApp 作为标准 daemon 渠道运行,支持持久化认证状态、配对日志、瞬时断线重连、自身回声过滤和文本回复。发布自动化生成更新元数据以及 macOS DMG、Windows NSIS、Linux AppImage/deb 产物,并在正式发布时强制要求签名材料。

仓库维护边界也已明确:OpenWork 通过只读上游 remote 和普通 merge commit 跟进 Qwen Code,并用 allowlist 将启用的 workflow 限定为 6 个由 OpenWork 负责的任务。Qwen 专属的 Pages、定时 E2E、bot、cache、stale、hygiene、素材清理、音频预构建和自托管 runner workflow 已删除,并记录恢复条件。保留的 CI 会让 OpenWork 使用托管 Windows runner,同时跳过 Qwen 的模型密钥 merge-queue 任务,因为本仓库没有对应 runner 和 OPENAI_* 凭据。

为什么需要

#81 建立 Tauri + Web Shell 架构,并证明 OpenWork 可以启动内置 Qwen 运行时和恢复会话。本 PR 在不恢复 Electron renderer、Electron IPC、第二套 Agent 运行时或旧消息网关的前提下,将这套架构补齐到产品可用状态。

采用堆叠 PR 可以保持评审边界清晰:先评审并合并 #81#81 落地后再把本 PR 的目标分支切换为 main

Reviewer Test Plan

如何验证

  1. 启动打包后的桌面应用,新建并重新打开会话,然后验证命令面板、思考快捷键、编辑器控制、主题、缩放、会话宽度、高对比和减少动画;确认偏好在重启后保留。
  2. 从聊天中打开 HTTP(S) 链接,确认它进入停靠浏览器,而会话链接仍留在已认证应用内;确认非法协议和错误会话深链被拒绝,并验证原生菜单中的浏览器和桌宠操作。
  3. 使用隔离的旧 OpenWork 数据首次启动,确认工作区和会话被导入且源数据未修改;再次启动确认幂等;修改一个已迁移文件后,确认回滚拒绝删除该文件。
  4. 添加 WhatsApp 和 Telegram 渠道。确认 WhatsApp 在配对完成前不会报告已连接,瞬时断线能够重连,自身回声会被忽略,文本回复沿标准渠道生命周期发送。
  5. 执行桌面发布 dry run,确认选择了预期的平台包和更新元数据;确认正式发布缺少必要的更新签名、macOS 或 Windows 签名材料时会失败关闭。
  6. 确认 workflow allowlist 仅接受保留的 6 个任务,OpenWork CI 选择 windows-2022,模型集成任务仅允许在 QwenLM/qwen-code 运行;在临时分支演练上游 merge,并确认未审核的 workflow 会在首次 push 前被移除。

证据(Before & After)

Before:#81 提供可运行的 Tauri/Web Shell 基线,其截图和 E2E 会话报告已附在该 PR;上述产品补齐能力在 PR1 中有意保留为空缺。

After:内置运行时通过健康检查,并从最终提交 ea125fc16f 重建了未签名的 macOS ARM64 DMG。最终阻断修复覆盖 385 个聚焦 Web Shell 测试、80 个 daemon-worker 测试、41 个 Rust 测试、4 个 WhatsApp 生命周期测试、迁移/发布契约、workflow allowlist、actionlint 和运行时打包;同一分支已通过的 broader build/typecheck 证据直接复用,没有重复执行。本堆叠 PR 不重复附加基线截图。

已测试平台

OS 状态
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

环境(可选)

macOS 打包后的 Tauri 应用,使用内置 Qwen 运行时;聚焦检查使用 Node.js 22 和仓库指定的 Rust toolchain。

风险与范围

  • 主要风险或权衡:原生 URL 所有权、迁移和发布签名跨越信任边界;这些路径使用精确运行时 origin 校验、协议/路径校验、带校验和的迁移报告和失败关闭的签名要求。
  • 未验证 / 范围外:未在本地启动 Windows 和 Linux 安装包。本地 macOS DMG 未签名、未公证;正式发布会在 updater、Apple 或 Windows 签名密钥未配置时失败关闭。旧 Electron renderer、IPC、Agent 运行时、更新器和消息网关不会恢复。
  • 破坏性变更 / 迁移说明:不破坏 PR1 的运行时契约。旧数据在首次启动时自动导入,保留源数据和凭据,并记录可审计的回滚报告。

关联项

堆叠于 #81。请先合并 #81,然后将本 PR 的目标分支切换为 main

@yiliang114
yiliang114 marked this pull request as ready for review August 13, 2026 05:50

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ea125fc16f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +7 to +11
import DE from '../../desktop/packages/shared/src/i18n/locales/de.json';
import ES from '../../desktop/packages/shared/src/i18n/locales/es.json';
import HU from '../../desktop/packages/shared/src/i18n/locales/hu.json';
import JA from '../../desktop/packages/shared/src/i18n/locales/ja.json';
import PL from '../../desktop/packages/shared/src/i18n/locales/pl.json';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Import shared assets through package boundaries

The added locale imports, along with the analogous imports in openwork/themes.ts, traverse from @qwen-code/web-shell into sibling desktop packages using relative paths. The root ESLint configuration treats import/no-relative-packages as an error, so npm run lint and preflight fail for this commit; export these resources from their owning package or expose them through a package-level import.

AGENTS.md reference: AGENTS.md:L255-L257

Useful? React with 👍 / 👎.

Comment on lines +123 to +128
const socket = makeWASocket({
auth: secureState,
browser: Browsers.macOS('OpenWork'),
logger: silentLogger,
printQRInTerminal: false,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Apply the configured proxy to WhatsApp

When a daemon channel runs in an environment where the configured proxy is the only route to the internet, the worker resolves and passes that proxy through ChannelBaseOptions, but this socket configuration never uses this.proxy. Unlike Telegram, WhatsApp's HTTP/WebSocket traffic therefore connects directly, causing initial pairing and reconnects to fail; configure Baileys' fetch and socket agents from the supplied proxy.

Useful? React with 👍 / 👎.

Comment on lines +474 to +477
const openBrowser = useCallback((url: string) => {
setBrowser({ url, open: true });
void invokeOpenWork('browser_open', { url })
.then(resizeBrowserDock)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the browser dock closed without Tauri

When the daemon-served Web Shell is opened in a regular browser and the user selects the Browser Dock palette action, window.__TAURI__ is absent, so invokeOpenWork() resolves successfully with undefined rather than rejecting. The state remains open, the success handler runs, and the UI displays a browser toolbar with no backing webview; gate this action on Tauri availability or fall back to ordinary browser navigation.

Useful? React with 👍 / 👎.

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