Skip to content

perf(tauri): Rust-native desktop event transport#242

Open
pascalandr wants to merge 12 commits into
NeuralNomadsAI:devfrom
Pagecran:pagec/rust-desktop-event-transport
Open

perf(tauri): Rust-native desktop event transport#242
pascalandr wants to merge 12 commits into
NeuralNomadsAI:devfrom
Pagecran:pagec/rust-desktop-event-transport

Conversation

@pascalandr
Copy link
Copy Markdown
Contributor

@pascalandr pascalandr commented Mar 22, 2026

Summary

  • switch the Tauri desktop runtime from the browser EventSource path to a native Rust desktop event transport while leaving browser and Electron unchanged
  • restore SSE heartbeat parity by parsing named event: frames and replying to codenomad.client.ping with an authenticated /api/client-connections/pong
  • add a Tauri-only settings toggle that lets the current device fall back to the browser EventSource transport without leaking that choice through shared config
  • remove the temporary benchmark harness from the shipped code now that the transport behavior has been validated

Benchmark

The temporary in-app benchmark harness used during validation has been removed from the final code, but the measured results are retained here for review context.

Real Tauri/WebView2 benchmark on Windows using the dedicated session:

  • workspace: D:\CodeNomad
  • session: ses_21feb15b3ffeLz3uRModK4KKnG

Short command:

  • node -e "for (let i = 1; i <= 400; i += 1) console.log('line ' + i)"

Results:

  • browser EventSource forced in Tauri:
    • timed out after 131479.7ms
    • sawWorking=false
    • reachedIdle=false
    • batchesReceived=84
    • eventsReceived=84
    • maxBatchSize=1
  • Rust-native transport:
    • completed in 1437.4ms
    • sawWorking=true
    • reachedIdle=true
    • batchesReceived=4
    • eventsReceived=45
    • maxBatchSize=27

Long heartbeat / stale-timeout validation:

  • command: powershell -NoProfile -Command Start-Sleep -Seconds 70
  • Rust-native transport:
    • completed in 71689.5ms
    • sawWorking=true
    • reachedIdle=true
    • batchesReceived=13
    • eventsReceived=72
    • maxBatchSize=25

Confirmed separately afterward: the native transport also behaves better on Linux.

Validation

  • cargo test named_ping_event_is_routed_to_ping_channel
  • cargo test session_cookie_is_attached_to_requests
  • cargo test --no-run
  • npx tsc --noEmit --pretty -p packages/ui/tsconfig.json
  • npx tsc --noEmit --pretty -p packages/server/tsconfig.json
  • manual Tauri/WebView2 benchmark on Windows
  • manual confirmation on Linux after the benchmark phase

Notes

  • this remains a Tauri-only transport; browser and Electron stay on the browser EventSource path
  • the Tauri fallback toggle is now genuinely device-local and restarts the local event stream immediately when changed
  • the long run validates heartbeat / stale-timeout robustness, not headline perf

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/23398482721

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/23398502150

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@pascalandr pascalandr marked this pull request as draft March 22, 2026 08:38
@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/23399446411

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/23401824896

Artifacts expire in 7 days.
Artifacts:

  • pr-242-a3e768c36a4a3a34df9c243e78bdf25e431c4d80-electron-linux
  • pr-242-a3e768c36a4a3a34df9c243e78bdf25e431c4d80-tauri-macos-arm64

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/23402541285

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/23410012218

Artifacts expire in 7 days.
Artifacts:

  • pr-242-aa0b3203b5910e5459cd1362b184d3f529ecd67e-electron-linux-rpm
  • pr-242-aa0b3203b5910e5459cd1362b184d3f529ecd67e-electron-linux

@pascalandr pascalandr force-pushed the pagec/rust-desktop-event-transport branch from 5f572c2 to 4448dd0 Compare March 29, 2026 21:19
@pascalandr pascalandr changed the title perf(tauri): move desktop event transport and transcript batching native perf(tauri): native desktop event transport with fast assistant streaming Mar 29, 2026
@pascalandr pascalandr force-pushed the pagec/rust-desktop-event-transport branch 7 times, most recently from 74ec719 to 302e87f Compare April 4, 2026 12:11
@pascalandr pascalandr marked this pull request as ready for review April 4, 2026 12:21
@pascalandr
Copy link
Copy Markdown
Contributor Author

I’d be happy to get a critical review on whether this direction makes sense upstream.

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 9, 2026

Hey @pascalandr ,

How does this Tauri specific change effect electron and server UI?

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 9, 2026

@CodeNomadBot

I want you to perform the gatekeeper checks for latest PR state

check for regressions
check for better possible implementations
Be the PR gatekeeper
Be ruthless about code quality

@pascalandr
Copy link
Copy Markdown
Contributor Author

Hey @pascalandr ,

How does this Tauri specific change effect electron and server UI?

Only commit 1 is Tauri-specific.
Electron and the browser/server UI still use the existing browser EventSource path; they do not use the Rust transport.

Commit 2 is intentionally cross-host: it optimizes how streaming updates are applied/rendered in the UI, so it should benefits Tauri, Electron, and the browser path alike.

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 9, 2026

Am I correct in understanding that each platform will be using their native EventSource path?

@pascalandr
Copy link
Copy Markdown
Contributor Author

In this PR:

  • Tauri switches to the nenw Rust-native transport
  • Electron and the browser/server UI keep the existing browser EventSource path

So only the Tauri transport changes here. The UI-side streaming optimizations are host-agnostic and sit below that transport choice.

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 9, 2026

@pascalandr - I am sure this works well but the problem is I don't have experience with Rust / Tauri . I am more Java / Node person and the Tauri app is 100% maintained by AI and community. The only reason it came in because people wanted it so AI made it.

I can't maintain Tauri only features as I can't code review them and EventSource being a core part any changes on it I will be totally reliant on AI or community for it.
So from my point of view, I see these platform specific changes

  • Are they necessary to support the platform?
  • Are these platform specific features bringing something really valuable?
  • Can we live without these features and have less code to maintain?
  • What are the trade-offs to not use them?

Would you help me decide these please?

@pascalandr
Copy link
Copy Markdown
Contributor Author

I see but TBH, the Rust/Tauri transport is the part I cared about most, because I use the Tauri client all day long.
But I do not have solid benchmark data yet, so I would not say this is needed for Tauri support. It is an optimization, not a requirement.
Are you looking for a community maintainer for the Tauri app before accepting this kind of change?

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 10, 2026

@CodeNomadBot

I want you to perform the gatekeeper checks for latest PR state

check for regressions
check for better possible implementations
Be the PR gatekeeper
Be ruthless about code quality

  • Also Read my comments and inform about possible knock-on effects on Electron and server.

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented Apr 10, 2026

I reviewed the latest PR state as a gatekeeper review.

My understanding of the request: evaluate the current PR for regressions, better implementation options, and specifically call out any knock-on effects on Electron and the server/browser UI discussed in this thread.

Findings:

  1. High: the new transport abstraction drops browser-side SSE ping/pong handling, which will regress Electron and the server/browser UI.

    • packages/ui/src/lib/server-events.ts:42-58 now calls connectWorkspaceEvents(...) without supplying onPing.
    • packages/ui/src/lib/event-transport.ts:24-30 still supports onPing, but only if the caller passes it through.
    • packages/ui/src/lib/api-client.ts:426-455 shows the browser EventSource path still emits codenomad.client.ping events.
    • packages/server/src/server/routes/events.ts:50-53,81-87 and packages/server/src/clients/connection-manager.ts:89-95 show those pings must be answered or the server times the client out after 45s.
    • packages/server/src/plugins/voice-mode.ts:16-29 shows at least one user-visible feature that depends on this connection tracking.
    • Before this PR, server-events.ts answered the ping by calling sendClientConnectionPong(...); that behavior is gone.
    • Result: Electron and the browser/server UI will silently lose their tracked client connection every ~45s on the browser EventSource path. That is exactly the cross-host knock-on effect your thread was asking about.
  2. High: the Tauri reconnect path clears the active session target and never restores it unless the user changes tabs/sessions again.

    • packages/ui/src/lib/native/desktop-events.ts:138-149 calls desktop_events_stop whenever the JS-side connection disconnects.
    • packages/tauri-app/src-tauri/src/desktop_event_transport.rs:364-371 clears state.active_target inside stop().
    • packages/ui/src/lib/server-events.ts:74-89 disconnects the current transport on every reconnect cycle.
    • packages/ui/src/App.tsx:266-280 only sends desktop_events_set_active_session(...) when activeStreamTarget() changes, not after transport reconnect.
    • Result: after the first native transport reconnect, the Rust side forgets which session is active, so the active-session-specific fast path can silently degrade until the user manually changes selection again. For a performance PR, losing the optimization after the first reconnect is a real behavioral regression.

Knock-on effects by host:

  • Commit 1 is still Tauri-only in intent, but it is not fully isolated operationally because the new shared transport abstraction in commit 2 regresses the browser EventSource path.
  • Electron and the server/browser UI do not take the Rust transport, but they do take the new connectWorkspaceEvents / ServerEvents path. So they are directly exposed to finding 1.
  • I did not find evidence that Electron/server pick up the Tauri-native batching/coalescing code itself. The cross-host risk is from the shared UI transport refactor, not from Rust code execution on those hosts.

Better implementation direction:

  • Preserve ping/pong at the abstraction boundary. Either keep the pong logic in ServerEvents, or make the browser transport implementation own ping replies so callers cannot accidentally omit them.
  • Split native transport teardown semantics into “temporary disconnect for reconnect” vs “full stop”, or keep active_target outside stop() so reconnects do not erase session targeting state.
  • Given the maintainer comments in this thread: this Tauri transport is an optimization, not a platform requirement, and it adds a large Tauri/Rust maintenance surface around a core event path. I would want hard benchmark evidence plus a simpler failure/reconnect story before accepting that maintenance cost upstream.

Validation notes:

  • I attempted cargo test --manifest-path packages/tauri-app/src-tauri/Cargo.toml desktop_event_transport, but it is blocked in this workspace by a missing packages/tauri-app/resources/server build resource.
  • I attempted UI typechecking, but the workspace does not currently have the UI/server dependencies installed, so that check is not meaningful here.

Gatekeeper verdict: not merge-ready. Both findings above are blocking regressions, and one of them hits Electron/server directly.

--
Yours,
CodeNomadBot

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 10, 2026

I see but TBH, the Rust/Tauri transport is the part I cared about most, because I use the Tauri client all day long. But I do not have solid benchmark data yet, so I would not say this is needed for Tauri support. It is an optimization, not a requirement. Are you looking for a community maintainer for the Tauri app before accepting this kind of change?

As of now, I want to keep native ( Tauri / Electron ) features to the bare minimum as my current process is to implement features in web and server and expect them to run on both Electron / Tauri without any changes. This helps me a lot in ways

  1. I don't have to test multiple platforms.
  2. I dont have to worry changing one will break the other
  3. I can be fairly confident on the changes.

I will need some time to work out what needs to be done for cases like this.
Community maintainers are good to have but currently my work on CodeNomad is what I do in my free time and waiting on features to be tested on different platforms by different maintainers might prove a bit slow.
I would surely love to have maintainers come and join but for the core product, not per platform.

I hope you understand.

@pascalandr
Copy link
Copy Markdown
Contributor Author

When you says not have to test multiple "platforms" do you mean Tauri / Electron or Windows/linux/Macos ?

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 16, 2026

@pascalandr - Sorry I missed your comment.

Multiple platforms = Tauri and Electron on different OSes ( Windows, MacOS and Linux )

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/25625484797

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@pascalandr
Copy link
Copy Markdown
Contributor Author

@CodeNomadBot

Please focus this review on multi-platform maintainability.

Be especially critical about anything that increases the long-term Tauri-specific maintenance surface, leaks platform-specific behavior into shared UI/runtime paths, or makes Electron and Tauri harder to keep aligned over time.

At the same time, keep in mind that the purpose of this PR is to restore a more reasonable performance balance for Tauri (especially WebView2 / GTK WebKit) compared to Electron, not to add platform-specific complexity for its own sake.

Also, please treat the debug / benchmark instrumentation as non-essential review noise for now unless it hides a real architectural or behavioral problem. The main review target is the transport and integration shape, not the temporary measurement scaffolding.

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented May 10, 2026

I reviewed the current PR state with the requested multi-platform maintainability scope.

My understanding of the request: re-check whether the newest transport/settings shape keeps Tauri-specific behavior isolated, avoids leaking platform choices into shared UI/runtime paths, and preserves Electron/Tauri alignment while still allowing Tauri to recover performance on WebView2 / GTK WebKit. I treated the benchmark harness as non-essential unless it changes shipped architecture or runtime behavior.

Findings:

  1. Medium: the new Tauri fallback preference is not actually device-local, even though it is described and surfaced as a device/runtime fallback. packages/ui/src/stores/preferences.tsx:70,150,191-192,468-475 stores useTauriNativeEventTransport in the shared ui config owner, and packages/ui/src/stores/preferences.tsx:846-849 mirrors every storage.configChanged update back into localStorage on every client. The runtime selector then reads that mirror in packages/ui/src/lib/event-transport.ts:57-59. This means one Tauri client can write a Tauri-only fallback choice through /api/storage/config/ui, have it broadcast to other browser/Electron/Tauri clients, and only the client that initiated updateUiSettings restarts the stream via packages/ui/src/stores/preferences.tsx:472-473. Other Tauri clients silently adopt the new localStorage value for the next connection/page load without an immediate restart, while browser/Electron receive inert Tauri-specific state. That is exactly the kind of cross-client/platform leakage that will be hard to reason about later. I would make the transport fallback source of truth genuinely local/device-scoped, or explicitly make it a shared workspace preference and restart/reconcile all affected Tauri clients when it changes.

  2. Low: the hidden forced-browser override is still present. packages/ui/src/lib/event-transport.ts:13,40-47 still supports ?forceBrowserEvents=1 and perf242-force-browser-events localStorage independently of the visible setting and benchmark gating. It is narrow and Tauri-only because the call site is guarded by runtimeEnv.host === "tauri", so I do not consider it an architectural blocker by itself. But it contradicts the “without query-string overrides” direction and leaves a second undocumented transport-selection path that future Electron/Tauri parity debugging has to remember.

What still looks good:

  • Browser/Electron continue to use the browser EventSource path through serverApi.connectEvents(...); the native bridge is only selected behind runtimeEnv.host === "tauri" in packages/ui/src/lib/event-transport.ts:57-81.
  • The shared ServerEvents dispatcher still owns batching into Solid updates and handler fanout, so the UI consumption model remains aligned across hosts.
  • The Rust transport remains isolated under packages/tauri-app/src-tauri/src/desktop_event_transport* plus a thin Tauri bridge in packages/ui/src/lib/native/desktop-events.ts.
  • The previous heartbeat/auth parity concerns still appear addressed: named SSE ping frames are parsed separately in Rust and pongs are sent with the shared session-cookie attachment path.
  • /api/perf-log remains behind PERF242_TRANSPORT_BENCH=1, and the UI benchmark component remains behind VITE_PERF242_TRANSPORT_BENCH=1 plus ?perf242TransportBench=1.

Maintainability verdict:

  • I would not block the native transport itself on multi-platform grounds; its runtime integration is mostly the minimal Tauri-only slice needed for the performance goal.
  • I would fix the fallback preference scoping before merge. The current shared-config plus localStorage mirror gives a Tauri-only runtime switch cross-client behavior while looking device-local in the UI, and that is a real long-term maintainability trap.
  • I would also remove, gate, or document the hidden forceBrowserEvents override before leaving draft.

Validation notes:

  • This pass was a code review only. I did not rerun the previously blocked local validation commands.
  • Prior validation in this workspace was blocked by missing packages/tauri-app/resources/server for the targeted Rust test and missing @types/node for the UI workspace typecheck.

--
Yours,
CodeNomadBot

@pascalandr
Copy link
Copy Markdown
Contributor Author

@CodeNomadBot
same review

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented May 10, 2026

I reviewed the latest PR state again with the same multi-platform maintainability scope.

My understanding of the request: verify whether the latest update fixes the two prior maintainability concerns (shared-config leakage for the Tauri fallback toggle and the hidden forced-browser override), while re-checking that the native transport remains a narrow Tauri-only integration and browser/Electron stay aligned on the existing browser EventSource path. I treated benchmark scaffolding as review noise unless it changed shipped behavior.

Findings:

No blocking or medium-severity multi-platform maintainability findings in the current state.

What changed since my last review:

  • The fallback toggle is now device-local. packages/ui/src/stores/preferences.tsx:392-394 initializes a local signal from readUseTauriNativeEventTransportPreference(), and packages/ui/src/stores/preferences.tsx:443-458 updates localStorage plus restarts only the local event stream. It no longer writes useTauriNativeEventTransport into the shared ui config owner.
  • Shared config broadcasts no longer mirror this Tauri-only transport choice into every client. packages/ui/src/stores/preferences.tsx:845-848 now only updates the shared UI bucket on storage.configChanged; it does not sync the transport setting into localStorage.
  • The settings/command registry still only exposes the toggle on Tauri via isTauriHost() at packages/ui/src/lib/settings/behavior-registry.ts:266-279.
  • The hidden forced-browser override is gone from the transport selector. packages/ui/src/lib/event-transport.ts:39-63 now selects native only from runtimeEnv.host === "tauri" && readUseTauriNativeEventTransportPreference(), then falls back to browser EventSource; there is no remaining forceBrowserEvents query-param or perf242-force-browser-events localStorage branch in that file.

What still looks good:

  • Browser/Electron continue through serverApi.connectEvents(...) and the browser EventSource path in packages/ui/src/lib/event-transport.ts:25-36,61-63.
  • The Tauri-native path remains isolated behind runtimeEnv.host === "tauri" in packages/ui/src/lib/event-transport.ts:43-56 and a thin bridge in packages/ui/src/lib/native/desktop-events.ts.
  • Shared UI event consumption still flows through ServerEvents and dispatchBatch(...) in packages/ui/src/lib/server-events.ts:67-101,142-159, so host-specific transport mechanics do not leak into feature-level event handlers.
  • Heartbeat/auth parity still appears preserved: Rust parses named codenomad.client.ping frames separately in packages/tauri-app/src-tauri/src/desktop_event_transport/stream.rs:174-212, and pongs use the same session-cookie attachment path in packages/tauri-app/src-tauri/src/desktop_event_transport/transport.rs:3-23.
  • Benchmark endpoints and UI harness remain gated as described by the PR body.

Residual non-blocking note:

  • The device-local Tauri transport state is now plumbed through the shared config context and command/settings helpers. That is not a blocker because the actual source of truth is localStorage and the visible setting is Tauri-gated, but it is worth keeping an eye on if more host-specific runtime toggles are added. A small local-device preferences layer could prevent the shared preferences store from accumulating inert platform fields over time.

Maintainability verdict:

  • The prior shared-config leakage concern is resolved.
  • The prior hidden override concern is resolved.
  • From the multi-platform maintainability angle, I do not see a remaining reason to block the current native transport slice. It is still Tauri-specific, but it is scoped to the runtime boundary and justified by the measured WebView2 / GTK WebKit performance gap.

Validation notes:

  • This pass was a code review only; I did not rerun local builds/tests in this workspace.
  • I relied on the PR’s updated validation notes for the latest successful cargo test, cargo test --no-run, and tsc runs.

--
Yours,
CodeNomadBot

Reintroduce the smallest Tauri-native event transport slice needed to compare it against the browser EventSource path on real sessions. Add a frontend/server benchmark hook so the desktop runtime can report end-to-end transport behavior without pulling in the broader UI performance changes from the original PR.

# Conflicts:
#	packages/tauri-app/src-tauri/src/cli_manager.rs

# Conflicts:
#	packages/tauri-app/src-tauri/src/main.rs
Handle named SSE ping events with explicit pong replies so the native transport survives the server heartbeat window, and remove the unused active-session fast path while keeping the benchmark harness authenticated.

# Conflicts:
#	packages/tauri-app/src-tauri/src/cli_manager.rs
Require the explicit bench build flag before the UI harness can be activated, remove query-string command overrides, gate perf logging behind a runtime flag, and add a regression test for named SSE ping frames.
Reuse the desktop event transport session cookie for the native /api/client-connections/pong request so heartbeat updates follow the same auth contract as the SSE stream, and cover it with a request-header regression test.
Expose a device-level setting that lets Tauri users disable the native Rust desktop event transport and fall back to the browser EventSource path when debugging transport issues or comparing behavior.

Persist the preference in UI settings, mirror it into localStorage so startup transport selection can read it synchronously, and restart the backend event stream immediately when the toggle changes so the new transport takes effect without a full app restart.

Validation: npx tsc --noEmit --pretty -p packages/ui/tsconfig.json; npx tsc --noEmit --pretty -p packages/server/tsconfig.json; cargo test --no-run
Move the Tauri native transport fallback toggle out of the shared UI config and treat it as a true device-local preference. The setting now lives only in local state plus localStorage, so browser, Electron, and other Tauri clients do not inherit a host-specific transport choice through storage broadcasts.

While updating the selector, remove the hidden forceBrowserEvents override so the visible Tauri fallback setting becomes the only shipped transport-selection path outside the benchmark build gates. Validation: npx tsc --noEmit --pretty -p packages/ui/tsconfig.json; npx tsc --noEmit --pretty -p packages/server/tsconfig.json; cargo test --no-run
@pascalandr pascalandr force-pushed the pagec/rust-desktop-event-transport branch from af6508d to 843a47c Compare May 11, 2026 06:17
@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/25761675193

Artifacts expire in 7 days.
Artifacts:

  • pr-242-843a47c98d6c8741f576d30cc2454c0695233718-tauri-windows
  • pr-242-843a47c98d6c8741f576d30cc2454c0695233718-tauri-macos
  • pr-242-843a47c98d6c8741f576d30cc2454c0695233718-tauri-linux
  • pr-242-843a47c98d6c8741f576d30cc2454c0695233718-electron-macos
  • pr-242-843a47c98d6c8741f576d30cc2454c0695233718-tauri-macos-arm64
  • pr-242-843a47c98d6c8741f576d30cc2454c0695233718-electron-windows
  • pr-242-843a47c98d6c8741f576d30cc2454c0695233718-electron-linux

The transport benchmark harness still called loadMessages with the old boolean force flag, which broke UI typecheck after the session API moved to an options object. This keeps the PR242 benchmark code compatible with the current Pagec_tauri integration baseline instead of leaving a validation-only regression on the stack.

The change is limited to the benchmark harness and preserves the existing forced reload behavior by switching to the current { force: true } call shape. This keeps the fix scoped to the branch that introduced the transport bench so downstream integrations can cherry-pick a normal commit without rewriting history.

Validation: npm run typecheck --workspace @codenomad/ui
Drop the temporary in-app benchmark harness, perf logging endpoint, and batch metrics now that the native desktop transport has been validated on Windows and Linux. Keep the shipped PR focused on the transport implementation and the user-facing Tauri fallback setting rather than the instrumentation used during evaluation.

The benchmark results are preserved in the PR description as historical validation, but the benchmark code itself no longer ships in the branch. Validation: npx tsc --noEmit --pretty -p packages/ui/tsconfig.json; npx tsc --noEmit --pretty -p packages/server/tsconfig.json; cargo test --no-run

# Conflicts:
#	packages/ui/src/transport-bench.tsx
@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/25959195000

Artifacts expire in 7 days.
Artifacts:

  • pr-242-654b424def481b8f5bd464839d0ef13db9d57958-tauri-macos
  • pr-242-654b424def481b8f5bd464839d0ef13db9d57958-electron-macos
  • pr-242-654b424def481b8f5bd464839d0ef13db9d57958-tauri-linux
  • pr-242-654b424def481b8f5bd464839d0ef13db9d57958-tauri-windows
  • pr-242-654b424def481b8f5bd464839d0ef13db9d57958-tauri-macos-arm64
  • pr-242-654b424def481b8f5bd464839d0ef13db9d57958-electron-windows
  • pr-242-654b424def481b8f5bd464839d0ef13db9d57958-electron-linux

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/25965871529

Artifacts expire in 7 days.
Artifacts: (none found on this run)

1 similar comment
@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/25965871529

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@pascalandr
Copy link
Copy Markdown
Contributor Author

The recorded results and manual testing on Linux and Windows confirm that this restores a more reasonable performance balance for WebView2 and GTK WebKit under heavy UI load.
I removed the temporary benchmark harness, so I think this is now ok to to merge if CodeNomadBot confirms.

@pascalandr
Copy link
Copy Markdown
Contributor Author

@CodeNomadBot

I want you to perform the gatekeeper checks for latest PR state

check for regressions
check for better possible implementations
Be the PR gatekeeper
Be ruthless about code quality

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented May 16, 2026

I performed the latest gatekeeper review for PR #242.

My understanding of the request: review the current, post-benchmark-harness-removal PR state ruthlessly for regressions, code-quality risks, and better implementation choices. I treated this as a merge gate, not just the earlier multi-platform maintainability pass.

Findings:

  1. Blocking: stale async connection failures can tear down a newer, healthy event stream. packages/ui/src/lib/server-events.ts:32-83 correctly captures generation and ignores stale onError, onOpen, and successful connection completions, but the catch path at packages/ui/src/lib/server-events.ts:78-82 unconditionally calls this.scheduleReconnect(). scheduleReconnect() then disconnects this.connection at packages/ui/src/lib/server-events.ts:91-94. That means an older connectWorkspaceEvents(...) attempt can reject after restart(...) or a newer connection attempt has already advanced connectGeneration, and its stale catch will disconnect the current stream and schedule an unnecessary reconnect. The native Tauri bridge makes this more likely because startup is now async and the local transport preference explicitly calls serverEvents.restart(...) at packages/ui/src/stores/preferences.tsx:454-457. The success path already has the right pattern at packages/ui/src/lib/server-events.ts:72-75; the failure path needs the same generation guard before scheduling reconnect, or scheduleReconnect should take/validate the expected generation.

Non-blocking notes:

  • The benchmark harness removal looks clean from shipped code. I did not find remaining perf242, transport-bench, perf-log, forceBrowserEvents, perf242-force-browser-events, or __TRANSPORT_TYPE references in the changed source.
  • The previous device-local fallback concern remains resolved: the Tauri fallback signal is local/localStorage-backed at packages/ui/src/stores/preferences.tsx:395-397,446-460, and shared storage.configChanged no longer mirrors it into localStorage.
  • The previous hidden forced-browser override concern remains resolved: packages/ui/src/lib/event-transport.ts:39-61 now selects native only from the Tauri host plus the local preference.
  • The Rust heartbeat/auth parity still looks intact: named codenomad.client.ping frames are separated in packages/tauri-app/src-tauri/src/desktop_event_transport/stream.rs:174-212, and pong requests use attach_session_cookie(...) in packages/tauri-app/src-tauri/src/desktop_event_transport/transport.rs:3-23.
  • The native transport implementation is larger than ideal, but it is isolated under desktop_event_transport* and has focused tests for the coalescing behavior. I do not see a smaller obvious implementation that would preserve the measured WebView2 / GTK WebKit improvement without moving batching/coalescing out of the browser.

Validation attempted:

  • cargo test --manifest-path packages/tauri-app/src-tauri/Cargo.toml named_ping_event_is_routed_to_ping_channel failed in this workspace before running tests because Tauri config points frontendDist at missing resources/ui-loading.
  • cargo test --manifest-path packages/tauri-app/src-tauri/Cargo.toml session_cookie_is_attached_to_requests failed for the same missing resources/ui-loading reason.
  • npx tsc --noEmit --pretty -p packages/ui/tsconfig.json failed because npx resolved the placeholder tsc package instead of a workspace compiler.
  • npx tsc --noEmit --pretty -p packages/server/tsconfig.json failed for the same placeholder tsc reason.
  • npm run typecheck --workspace @codenomad/ui also failed in this workspace due missing installed dependencies/types such as solid-js, @opencode-ai/sdk, and Node test types.
  • npm run typecheck --workspace @neuralnomads/codenomad failed due missing @types/node.

Gatekeeper verdict:

Do not merge yet. The remaining issue is small and localized, but it is exactly in the shared event-stream lifecycle code and can cause a newer active stream to be disconnected by a stale failed connect attempt. Add the generation guard on the connect() catch path, then this should be ready for another quick final pass.

--
Yours,
CodeNomadBot

Guard the async event-stream connect failure path with the same generation check used by the success callbacks so an older rejected connection attempt cannot tear down a newer healthy stream.

This keeps Tauri restarts and other reconnect races from disconnecting the active transport after the local desktop transport preference changes or another connection attempt wins first. Validation: npx tsc --noEmit --pretty -p packages/ui/tsconfig.json; npx tsc --noEmit --pretty -p packages/server/tsconfig.json
@pascalandr
Copy link
Copy Markdown
Contributor Author

@CodeNomadBot
same review

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented May 16, 2026

I performed the latest gatekeeper review for PR #242 after the follow-up fix.

My understanding of the request: run the same merge-gate review as before, specifically confirming whether the stale async event-stream connect failure issue is fixed, while re-checking the transport/fallback/benchmark-removal areas for regressions.

Findings:

No blocking findings in the current PR state.

What changed since the last gatekeeper pass:

  • The previous blocker is fixed. packages/ui/src/lib/server-events.ts:78-86 now checks generation !== this.connectGeneration before logging and calling scheduleReconnect() from the async connect() catch path. That matches the existing guards for onError, onOpen, and stale successful connections at packages/ui/src/lib/server-events.ts:46-58,72-75, so an old failed connect attempt should no longer disconnect a newer healthy stream.

Regression checks:

  • Browser/Electron still stay on the browser EventSource path through packages/ui/src/lib/event-transport.ts:25-36,60-61.
  • Tauri native transport selection remains host-gated and preference-gated at packages/ui/src/lib/event-transport.ts:39-55.
  • The Tauri fallback remains local-device scoped: packages/ui/src/stores/preferences.tsx:395-397,446-460 uses the local preference/localStorage path and restarts only the local stream.
  • Native event listeners still filter by generation before delivering batches/statuses in packages/ui/src/lib/native/desktop-events.ts:32-35,50-56, and pending pre-start events are flushed only after the expected generation is known.
  • Heartbeat/auth parity still looks intact: Rust routes named codenomad.client.ping frames to the ping channel in packages/tauri-app/src-tauri/src/desktop_event_transport/stream.rs:174-212, and pongs still use cookie attachment in packages/tauri-app/src-tauri/src/desktop_event_transport/transport.rs:3-23.
  • Temporary benchmark/debug harness removal still looks clean. I found no remaining changed-source references to perf242, transport-bench, perf-log, forceBrowserEvents, perf242-force-browser-events, or __TRANSPORT_TYPE.

Code-quality verdict:

  • The implementation is still a non-trivial native transport, but the complexity is isolated at the Tauri/runtime boundary and covered by focused Rust tests for parsing/auth/coalescing behavior.
  • I do not see a simpler shipped implementation that preserves the measured WebView2 / GTK WebKit improvement without pushing the same batching/coalescing work back into the browser.
  • From the gatekeeper perspective, this is now acceptable to merge once normal CI is green.

Validation attempted in this workspace:

  • cargo test --manifest-path packages/tauri-app/src-tauri/Cargo.toml named_ping_event_is_routed_to_ping_channel is still blocked before tests run because Tauri config points frontendDist at missing resources/ui-loading.
  • npm run typecheck --workspace @codenomad/ui is still blocked by missing installed UI dependencies/types, including solid-js, @opencode-ai/sdk, Tauri plugin types, and Node test types.
  • npm run typecheck --workspace @neuralnomads/codenomad is still blocked by missing @types/node.

Gatekeeper verdict:

No objection to merge from this review, subject to the project’s normal CI/build checks passing in the fully provisioned environment.

--
Yours,
CodeNomadBot

@pascalandr
Copy link
Copy Markdown
Contributor Author

@CodeNomadBot

Please confirm this PR pay attention about multi-platform maintainability.

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented May 16, 2026

I re-confirmed PR #242 specifically from the multi-platform maintainability angle.

My understanding of the request: confirm whether this PR is acceptable after the latest gatekeeper pass, with extra attention to whether the Tauri-native transport creates long-term platform divergence, leaks Tauri behavior into shared UI/runtime code, or leaves browser/Electron harder to keep aligned.

Findings:

No blocking multi-platform maintainability findings in the current state.

Confirmation points:

  • Browser and Electron remain on the existing browser EventSource path. packages/ui/src/lib/event-transport.ts:45-61 only attempts the native transport when runtimeEnv.host === "tauri"; all other hosts fall through to connectBrowserWorkspaceEvents(...).
  • The Tauri fallback setting is device-local and does not leak through shared config. packages/ui/src/stores/preferences.tsx:395-397,446-460 reads/writes the local transport preference and restarts only the local stream; the shared ui config bucket is not used as the source of truth for this runtime choice.
  • The previous event-stream lifecycle blocker remains fixed. packages/ui/src/lib/server-events.ts:78-86 now ignores stale async connect failures before scheduling reconnect, matching the existing generation guards for open/error/success paths.
  • The Tauri-specific bridge remains thin. Shared UI code still consumes normalized batches through ServerEvents, while Tauri mechanics stay behind packages/ui/src/lib/native/desktop-events.ts and packages/tauri-app/src-tauri/src/desktop_event_transport*.
  • Heartbeat/auth parity remains aligned with the browser path: Rust parses named codenomad.client.ping frames separately and sends authenticated pongs through the shared cookie attachment path.
  • Temporary benchmark/debug scaffolding is not present in changed shipped source. I found no remaining references to perf242, transport-bench, perf-log, forceBrowserEvents, perf242-force-browser-events, or __TRANSPORT_TYPE.

Maintainability verdict:

This PR pays sufficient attention to multi-platform maintainability. It adds Tauri-specific complexity, but the complexity is isolated at the runtime boundary, justified by the measured WebView2 / GTK WebKit performance gap, and does not force browser/Electron onto a divergent shared runtime path.

I have no objection to merge from the multi-platform maintainability perspective, subject to normal CI/build checks passing in the fully provisioned environment.

--
Yours,
CodeNomadBot

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.

2 participants