feat(desktop): complete OpenWork Tauri parity - #82
Conversation
# Conflicts: # .github/workflows/desktop-release.yml
…openwork-tauri-pr2 # Conflicts: # packages/desktop-shell/scripts/prepare-runtime.js # packages/desktop-shell/scripts/smoke-runtime.js
There was a problem hiding this comment.
💡 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".
| 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'; |
There was a problem hiding this comment.
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 👍 / 👎.
| const socket = makeWASocket({ | ||
| auth: secureState, | ||
| browser: Browsers.macOS('OpenWork'), | ||
| logger: silentLogger, | ||
| printQRInTerminal: false, | ||
| }); |
There was a problem hiding this comment.
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 👍 / 👎.
| const openBrowser = useCallback((url: string) => { | ||
| setBrowser({ url, open: true }); | ||
| void invokeOpenWork('browser_open', { url }) | ||
| .then(resizeBrowserDock) |
There was a problem hiding this comment.
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 👍 / 👎.
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 serveremains 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
mainafter #81 lands.Reviewer Test Plan
How to verify
windows-2022, and the model-backed integration job is repository-gated toQwenLM/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
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
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
如何验证
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 不重复附加基线截图。已测试平台
环境(可选)
macOS 打包后的 Tauri 应用,使用内置 Qwen 运行时;聚焦检查使用 Node.js 22 和仓库指定的 Rust toolchain。
风险与范围
关联项
堆叠于 #81。请先合并 #81,然后将本 PR 的目标分支切换为
main。