Skip to content

Automate Tauri command registration via tauri-helper.#3679

Merged
louis030195 merged 5 commits into
screenpipe:mainfrom
divanshu-go:fix-tauri-specta
May 29, 2026
Merged

Automate Tauri command registration via tauri-helper.#3679
louis030195 merged 5 commits into
screenpipe:mainfrom
divanshu-go:fix-tauri-specta

Conversation

@divanshu-go
Copy link
Copy Markdown
Contributor

Description

Replaces hand-maintained Tauri invoke-handler and tauri-specta command lists with build-time auto-collection using tauri-helper at 65d4f27. Adds drift tests so checked-in TypeScript bindings stay in sync with Rust, and regenerates lib/utils/tauri.ts with stable alphabetical ordering.

Motivation

The screenpipe Tauri app had grown to ~200 commands spread across many modules. Every new #[tauri::command] required manual updates in three places:

  1. tauri::generate_handler![...] in main.rs
  2. tauri_specta::collect_commands![...] in main.rs
  3. Often a follow-up regeneration of lib/utils/tauri.ts

Missing a step caused runtime handler errors or stale frontend types. This PR removes that maintenance burden and adds CI-friendly guards against binding drift.

Changes

Rust backend (apps/screenpipe-app-tauri/src-tauri)

Area Change
Dependency Adds tauri-helper as a git dependency (build + runtime) pinned to 65d4f27
build.rs Calls tauri_helper::generate_command_file with collect_all: true to scan the workspace for all #[tauri::command] functions at compile time
main.rs Removes ~200 lines of manual command lists; uses tauri_helper::specta_collect_commands!() and tauri_helper::tauri_collect_commands!() instead
main.rs Introduces define_specta_builder! macro shared by debug export, tests, and the specta registry
specta_bindings.rs New module with TypeScript export helpers and drift tests
package.json Adds bindings:check and bindings:generate bun scripts (wrappers around the drift tests below)

Frontend (apps/screenpipe-app-tauri)

Area Change
lib/utils/tauri.ts Regenerated from the auto-collected command surface; commands and types are alphabetically ordered for stable diffs

How it works

At build time, tauri-helper walks the Cargo workspace, finds every function annotated with #[tauri::command], and writes generated macro input to target/tauri_commands_list/. At compile time:

  • specta_collect_commands!() expands to the full tauri_specta::collect_commands![...] list
  • tauri_collect_commands!() expands to tauri::generate_handler![...]

Adding a new command is now: write #[tauri::command], rebuild — no list editing.

Binding export & drift detection

From apps/screenpipe-app-tauri/:

# Fail if lib/utils/tauri.ts drifted from Rust (run in CI / before PR)
bun run bindings:check

# Regenerate lib/utils/tauri.ts after adding or changing #[tauri::command]
bun run bindings:generate

Equivalent cargo test invocations (what the bun scripts call under the hood):

cargo test -p screenpipe-app tauri_bindings_are_current --manifest-path src-tauri/Cargo.toml -- --nocapture
UPDATE_TAURI_BINDINGS=1 cargo test -p screenpipe-app export_typescript_bindings --manifest-path src-tauri/Cargo.toml -- --nocapture

In debug builds, main.rs also calls write_bindings_if_changed_with on startup so local dev stays in sync without manual export.

Test plan

  • cargo check -p screenpipe-app succeeds with the pinned tauri-helper git dependency
  • bun run bindings:check passes in apps/screenpipe-app-tauri (checked-in tauri.ts matches Rust)
  • bun run typecheck passes in apps/screenpipe-app-tauri
  • bun run build completes (Next.js + pre_build)
  • App launches; spot-check invoke paths (settings load/save, recording start/stop, permissions)
  • Add a new #[tauri::command] in a submodule and confirm it appears in the handler without editing main.rs

Notes

  • No behavior change intended — this is a registration and tooling refactor. Command names and signatures are unchanged; only how they are collected and exported differs.

  • Stable diffstauri.ts reordering is cosmetic (alphabetical).

Copy link
Copy Markdown
Collaborator

@louis030195 louis030195 left a comment

Choose a reason for hiding this comment

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

@divanshu-go can you remove unrelated change from the pr

generated by the screenpipe pr-review pipe (https://screenpi.pe), not written by a human — reply and tag @louis030195 if it got something wrong.

Replace manual handler and specta command lists with build-time auto-collection,
add specta_bindings export/drift tests, and regenerate tauri.ts with stable ordering.
…better consistency. Change bigint types to number in various functions and types for improved compatibility across the codebase.
@divanshu-go
Copy link
Copy Markdown
Contributor Author

divanshu-go commented May 29, 2026

@louis030195 removed the unrelated changes from this PR.

I also changed Specta’s bigint export from BigInt to Number in specta_bindings.rs:

Typescript::default().bigint(BigIntExportBehavior::Number)

Reason: Tauri IPC serializes through JSON, so the frontend receives JS number values at runtime, not bigint. This only affects the generated TypeScript bindings. Rust still uses u64 / i64, and serde behavior is unchanged.

The values we expose are safely below Number.MAX_SAFE_INTEGER, so number matches the real runtime behavior without precision issues.

Screenshot 2026-05-29 at 5 47 53 PM
Screen.Recording.2026-05-29.at.5.49.23.PM.mov
Screenshot 2026-05-29 at 5 51 28 PM

@divanshu-go
Copy link
Copy Markdown
Contributor Author

@louis030195

Screen.Recording.2026-05-29.at.6.25.57.PM.mov

Louis Beaumont and others added 2 commits May 29, 2026 08:15
Resolve the lib/utils/tauri.ts conflict by regenerating the bindings
against the merged Rust command surface. main added
`display_preview: Option<String>` to `pi_queue_prompt`, so the
regenerated `piQueuePrompt` binding now carries the 4th `displayPreview`
argument. `bun run bindings:check` (tauri_bindings_are_current) passes
and `next build` succeeds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
main advanced while resolving the PR. Re-merge brings in the
feat(export) meeting/range MP4 export plus the v2.4.294/295 bumps.

Conflict was only in main.rs invoke_handler: main registered the new
`meeting_export::export_recording` command in the manual
generate_handler! list that this PR replaces with
`tauri_helper::tauri_collect_commands!()`. Kept the macro and dropped
the manual entry — `export_recording` is auto-collected (it has
`#[tauri::command]`), and is correctly absent from tauri.ts since it
has no `#[specta::specta]` (frontend calls it via raw invoke).

Regenerated bindings (zero diff), drift test and `next build` pass,
Cargo.lock synced to 2.4.295.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@divanshu-go
Copy link
Copy Markdown
Contributor Author

@louis030195 I'm currently rebasing it , So I will ping you once its done.

@louis030195 louis030195 merged commit c2495b7 into screenpipe:main May 29, 2026
9 of 12 checks passed
@divanshu-go
Copy link
Copy Markdown
Contributor Author

@louis030195
#3688

louis030195 pushed a commit that referenced this pull request May 30, 2026
… auto-collect

- Resolve main.rs conflict in favor of main's tauri_collect_commands!()
  auto-collection (PR #3679) — drops the manual generate_handler! list.
- Add #[specta::specta] to await_safe_restart so the auto-collector actually
  registers it (without it the command is silently excluded and the frontend
  raw invoke("await_safe_restart") would fail at runtime). get_boot_phase
  already had both attrs.
- Cargo.lock: take main's superset (#3660 adds no deps).
- Add crates/screenpipe-audio/examples/race_repro.rs: a standalone harness
  that reproduces the ORT teardown SIGSEGV (#3622) 40/40 in RACE mode and
  stays clean 40/40 in GATED mode (validating the boot-ready gate).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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