Windows desktop port#520
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Windows CI jobs for signed and PR builds, pins and provisions Windows ONNX Runtime with checksum verification, tightens Tauri filesystem capabilities to ChangesWindows Desktop Build Support
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying maple with
|
| Latest commit: |
02da761
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a5f67da1.maple-ca8.pages.dev |
| Branch Preview URL: | https://windows-pr1-compile-launch.maple-ca8.pages.dev |
bbb7960 to
a4161cd
Compare
|
I've been making significant updates to the build processes, you'll likely want to rebase and standardize around them at some point |
1aa2673 to
2c4e927
Compare
19b863d to
4e074dc
Compare
Rebased the PR and updated to follow some of the new patterns you set up. All builds are passing and I was able to download the windows installer and run on my VM successfully |
4e074dc to
c5e79a2
Compare
|
Does this have full feature compatibility? |
most features work - login, chat, voice record, file picker, search, folders. I'll be following up with some other updates over the next couple of days -
|
|
I’d say keeping working on that in a single PR then. No point in splitting things across many PRs and merging in incomplete code. also don’t spend any more extra time on any cicd or development setup scripts or anything. All of that is going to be redone with my new nixos reproducible build setup. |
Sounds good, happy to run it that way. I'll close my other PR and convert this back to a draft for now so it can all land together. 👍 |
022613d to
260af74
Compare
|
I tested this on Windows 11 ARM in UTM. TTS setup fails at the first model download. The Tauri log only shows:
and then no success/failure line. The dialog shows From the code, the failure likely happens around Could we log the exact download error/status and surface |
|
these logs are expected, but it's going to be hard to test until we build release builds for these. can you double check the logic at least and verify that it should work correct? |
|
Also hard to test oauth deeplink flow since CICD build for the dev environment but I think it might work just fine based on the logs: however I do not know what's up with that system32 log at the end. |
|
Also i fixed some cicd things in master, if you rebase it should fix the failures we were having here. |
Three minimum-viable changes to unblock building Maple on Windows. Atomic migration, keyring storage, signing, TTS DLL shipping, and the CI matrix job are deferred to follow-up epics. tauri.conf.json (MPLR-uyqowcnn / 1a): - bundle.targets switched from "all" to an explicit list excluding "msi". Tauri's WiX template hard-codes HKLM + perMachine install, which would shadow the HKCU keys we rely on for cloud.opensecret.maple deep links. - bundle.windows.nsis.installMode = "currentUser" so the NSIS installer is per-user (no UAC) and writes deep-link registration under HKCU. - bundle.windows.webviewInstallMode.type = "downloadBootstrapper" set explicitly to avoid surprise behavior if the Tauri default changes. capabilities/default.json (MPLR-zivybmgl / 1b): - Dropped $HOME/.config/maple/** scope entries from every fs:allow-* permission. The path tokens don't resolve to anything meaningful on Windows, no JS code touches them via the Tauri fs plugin, and proxy.rs writes via raw std::fs which bypasses the capability system entirely. $APPCONFIG/** entries are kept. src/proxy.rs (MPLR-oshibkah / 1c): - get_config_path now takes &AppHandle and resolves to %APPDATA%\cloud.opensecret.maple\ on Windows via Tauri's path resolver. macOS and Linux behavior is byte-identical (still ~/.config/maple/). - AppHandle is plumbed through save_proxy_config, load_saved_proxy_config, start_proxy, load_proxy_config, save_proxy_settings, and the auto-start initializer. Frontend invoke() calls are unchanged — Tauri auto-injects AppHandle on commands. - USERPROFILE fallback removed; Windows now uses the proper Tauri path. cargo check + cargo clippy -D warnings + cargo fmt --check all pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces Windows as a third desktop build target across both desktop CI
workflows. Both jobs are born conformant with the patterns shipped during
PR review (pinned actions, Bun 1.3.5, Rust 1.95.0, sha256-verified binary
fetches via onnxruntime-pins.sh + sibling helper script).
desktop-build.yml (MPLR-hzehaxpp / 1e):
- New build-windows job runs on push to master, mirrors build-macos /
build-linux step-for-step, builds via tauri-action (signing env wired
up so the action doesn't error mid-build, though Authenticode is
deliberately out of scope here), uploads the .exe artifact.
- All third-party actions SHA-pinned to the same commits used by the
Linux/macOS jobs: actions/checkout, oven-sh/setup-bun,
dtolnay/rust-toolchain, actions/cache, tauri-apps/tauri-action,
actions/upload-artifact.
- bundle.targets in tauri.conf.json already constrains the Windows build
to NSIS (MPLR-zsvmhjjx / 1i), so the redundant `--bundles nsis`
tauri-action arg is omitted.
desktop-pr-build.yml (MPLR-hzehaxpp / 1e):
- Parallel build-windows job runs on pull_request, modeled on the
existing macOS/Linux PR jobs: no secrets, no codesigning, no updater
artifacts (`bun tauri build --no-sign --config '{"bundle":{"createUpdaterArtifacts":false}}'`),
dev-environment VITE URLs, artifact suffixed `-pr`.
sccache install (MPLR-gelmlpfg / 1h):
- Mirrors the Linux job's style (long-form curl, `sha256sum --check -`,
current-dir extract). Windows twist: download/verify/extract run inside
a subshell cd'd to RUNNER_TEMP so all paths stay relative. MSYS2 tar
mangles absolute D:\ paths passed via -C/-f even with --force-local;
relative paths sidestep it. Inline comment explains.
ONNX Runtime install (MPLR-hzehaxpp / 1e):
- New provide-windows-onnxruntime.sh helper mirrors
provide-linux-onnxruntime.sh one-for-one: same sha256_file /
verify_sha256 helpers, archive + DLL double SHA256 verify, emits
ORT_LIB_LOCATION / ORT_SKIP_DOWNLOAD / ORT_DYLIB_PATH for the
GITHUB_ENV file. Workflow step reduces to a single invocation piped to
GITHUB_ENV.
- onnxruntime-pins.sh extended with windows_x64_archive_sha256 and
windows_x64_dll_sha256 lookups for 1.22.0 (matches the existing
linux_x64 pattern).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
proxy.rs writes proxy_config.json to ~/.config/maple on macOS/Linux (byte-identical behavior deferred to PR3's app_config_dir() unification), but the capability only allowed $APPCONFIG/** ($APPCONFIG resolves to the bundle-identifier dir, e.g. ~/.config/cloud.opensecret.maple on Linux). Those writes fell outside the allowed scope and failed with permission errors. Restore the $HOME/.config/maple entries to match proxy.rs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The build-windows job signs builds and tauri.conf.json sets createUpdaterArtifacts: true, so Tauri emits .nsis.zip and .nsis.zip.sig alongside the .exe installer. The upload step only globbed *.exe, silently discarding the updater artifacts (inconsistent with the Linux job). Add the .nsis.zip and .nsis.zip.sig globs so auto-update artifacts are preserved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On Windows the proxy config lives in the roaming %APPDATA% profile, so a plaintext api_key could sync across machines in a domain/AAD environment. Store it in Credential Manager via keyring (windows-native) and scrub it from the JSON; restore it on load. If secure storage is unavailable, fall back to plaintext-in-JSON. All keyring code and the dependency are gated to target_os="windows" — macOS/Linux keep their existing local plaintext-with-0o600 behavior, byte-for-byte unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On Windows, OAuth/payment deep links only reach the app if HKCU\Software\Classes\cloud.opensecret.maple\shell\open\command points at the running exe. A missing or stale key (installer skipped, dev build deleted, exe moved) silently breaks the OAuth callback with no signal. Log the result of DeepLinkExt::is_registered() once at startup so support can diagnose "the callback button does nothing" reports. Windows-gated; no behavior change on macOS/Linux. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The "Desktop" card listed only "macOS • Linux". Windows is now a supported desktop target, so include it. Listed last to reflect relative priority. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
maple.exe links onnxruntime.dll by ordinal. On a clean Windows install the
loader binds that import to the OS-shipped Windows-ML onnxruntime.dll (a
forwarder to onnxruntime_x64.dll, currently v1.17), which lets the app launch
but hangs TTS at the first Session::builder call.
Ship ONNX Runtime 1.22.0 and its four MSVC C++ runtime DLLs (VCRUNTIME140,
VCRUNTIME140_1, MSVCP140, MSVCP140_1) next to maple.exe so the executable's
own directory wins the Windows DLL search order over System32. The four CRT
DLLs are deployed app-local (rather than via vc_redist) to avoid a UAC prompt
on the per-user install.
Deployment uses an NSIS installer hook, not bundle.resources: in Tauri 2.11 a
resources map supplied via the platform config gets the DLLs into the installer
payload but not into the NSIS install file-list, so they never land in the
install dir (verified: only maple.exe + uninstall.exe were installed). The hook
copies them explicitly into $INSTDIR and removes them on uninstall.
- resources/windows/install-dlls.nsh: NSIS_HOOK_POSTINSTALL File-copies the 5
DLLs from <src-tauri>/resources/windows into $INSTDIR (anchored on
${MAINBINARYSRCPATH}); NSIS_HOOK_PREUNINSTALL deletes them.
- tauri.windows.conf.json: register the hook via bundle.windows.nsis.installerHooks
(Windows-only; macOS/Linux/iOS unaffected).
- resources/windows/: README + .gitignore (the redistributable DLLs are staged
at build time, not committed).
- desktop-pr-build.yml / desktop-build.yml: stage the 5 DLLs into
resources/windows before the Tauri build, from the already-downloaded ORT
(ORT_DYLIB_PATH) and the MSVC CRT redist located via vswhere (year/edition
agnostic, with a System32 fallback).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The desktop menu was built as a flat in-window bar on Windows/Linux (About / Check for Updates / Undo / Redo / Cut / Copy / Paste / Select All / Quit), adding a cluttered, dated row at the top of the window. The edit items are handled natively by the webview regardless of the menu, About is available in the in-app account menu, and updates are applied by the automatic check (startup + hourly), so the bar added only noise. Gate the entire menu-creation block (and its event handler) to macOS, which keeps its proper nested app/Edit submenus. Windows and Linux now get a clean window with just the title bar. The updater auto-check loop is untouched and still uses check_for_updates, so no code is orphaned. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A hard delete_credential() failure left the stale credential in place but still reported success, so save_proxy_config scrubbed the key from the JSON. On the next load the surviving credential won over the (empty) JSON value and the cleared key was silently resurrected. Propagate the delete failure instead of warning + returning Ok(true), and have save_proxy_config surface a clear failure rather than scrubbing the JSON. Store failures keep the existing plaintext-fallback behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
a925930 to
bf6c3b1
Compare
Every failure branch in tts_download_models returned Err(String) without logging, so a failed download produced no log line after "Downloading TTS model: ..." and the exact cause was invisible. The frontend compounded this with `err instanceof Error ? err.message : "..."`, which discards the plain-string error a Tauri Result<_, String> rejects with — the user only ever saw a generic "Failed to download TTS models". - tts.rs: wrap the flow so any propagated error is logged once via log::error!; include the URL (and existing HTTP status) on the network branches so HTTP / TLS / timeout / DNS are distinguishable from size / checksum failures. - TTSContext.tsx: surface a string rejection directly so the real message reaches the dialog (covers download and load failures). Reported by @AnthonyRonning testing on Windows 11 ARM (PR #520 review). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Done in
To be clear, this makes the failure visible — it doesn't fix it. I deliberately didn't guess at the cause, since the candidates need different fixes (the model URLs are HuggingFace LFS links that 302-redirect to a CDN, so it could be the redirect failing on the VM, a timeout, an error page failing the checksum, or TLS). Could you re-run on this build and paste the dialog error + the |
Checked — the client side is correct. The error is server-side: Heads-up that it'll keep erroring post-release until that entry lands (keyed |
Benign — that's the The actual deep-link URL is |
Done — rebased onto master. #562 (tagged-appimage-tools) cleared the |
|
Maybe it was a fluke or my environment but the TTS worked this time! even played in the vm. I think everything as far as we can currently test and hypothesis is in a really solid position! I think it makes sense to merge this now. I will iterate on some nixos and signed release build stuff from here. great work getting this working end to end! |
Summary
Brings the Tauri desktop app to Windows (x64, NSIS installer).
This is the single consolidated PR for the Windows port. Per maintainer direction it replaces the earlier stacked PR-per-slice plan and grows until Windows reaches feature parity, rather than merging incomplete slices across many PRs.
Build/CI/dev-setup is intentionally minimal here. The reproducible build + release pipeline (likely cross-compilation via nix) is owned by the maintainer and lands after the Windows app is in a good place. The
windows-latestCI job in this PR is an interim compile/build gate only — a placeholder to keep the app building until that pipeline replaces it.What's included
windows-latestjobs produce an unsigned NSIS build on both master-push and PRs.%APPDATA%(Tauriapp_config_dir()); API key stored in Windows Credential Manager (keyring) and scrubbed from the JSON, with plaintext fallback if secure storage is unavailable. macOS/Linux behavior byte-for-byte unchanged.cloud.opensecret.maple://registered via the NSIS template + runtimeregister();installMode: currentUser;msiexcluded from bundle targets. Adds a Windows startup diagnostic loggingis_registered()to debug "OAuth callback does nothing" reports.Still pending (toward full feature parity)
onnxruntime.dllon WindowsScope notes
/downloadspage is left as-is (superseded by trymaple.ai/research#download).Test plan
build-windowsCI (master-push + PR) stays green%APPDATA%config + Credential Managerstart cloud.opensecret.maple://auth?...from cmd focuses the app and logs the deep link🤖 Generated with Claude Code