[package]
name = "OpenHuman"
version = "0.54.10"
description = "OpenHuman - AI-powered Super Assistant"
authors = ["OpenHuman"]
edition = "2021"
default-run = "OpenHuman"
autobins = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
# The `_lib` suffix may seem redundant but it is necessary
# to make the lib name unique and wouldn't conflict with the bin name.
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
name = "openhuman"
crate-type = ["staticlib", "cdylib", "rlib"]

[[bin]]
name = "OpenHuman"
path = "src/main.rs"

[build-dependencies]
tauri-build = { version = "2", features = [] }
serde_json = "1"

[dependencies]
# Tauri core and plugins.
#
# The only supported runtime is CEF (Chromium Embedded Framework) via
# `tauri-runtime-cef` — CI builds, release installers, and local `cargo tauri
# dev` all run against CEF. The `[patch.crates-io]` block at the bottom of this
# file pins every tauri crate and plugin to the `feat/cef` branch on github so
# CEF symbols are in scope, and `cef-dll-sys`'s build script auto-downloads the
# Chromium runtime for the current target on first build.
tauri = { version = "2.10", default-features = false, features = [
    "cef",
    "common-controls-v6",
    "devtools",
    "macos-private-api",
    "tray-icon",
    "unstable",
    "webview-data-url",
] }
tauri-plugin-deep-link = "2.0.0"
tauri-plugin-global-shortcut = "2"
tauri-plugin-notification = { path = "vendor/tauri-plugin-notification" }
tauri-plugin-opener = "2"
# Prevents a second launch from racing into CEF init and hitting the
# `cef::initialize(...) != 1` cache-lock panic seen in production
# (Sentry OPENHUMAN-TAURI-A). The plugin acquires a per-identifier
# lock before any tauri::Builder work happens, so the secondary
# process exits cleanly after handing its argv to the primary. The `deep-link`
# feature forwards second-launch deep-link payloads to the primary instance on
# Windows/Linux, which is required for hot-instance OAuth callbacks.
tauri-plugin-single-instance = { version = "2", features = ["deep-link"] }
# Auto-update for the Tauri shell itself. The core sidecar already has its own
# updater (see `core_update.rs`); this plugin handles the .app/.exe/.AppImage
# bundle. Both are needed because shipping a new RPC method requires both
# pieces in lockstep, and on macOS the .app bundle is what carries TCC grants.
tauri-plugin-updater = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
toml = "0.8"
directories = "5"
# Used by gmail/cdp_fetch for decoding binary IO.read chunks. Base64 is
# only emitted by CDP IO.read when the stream contains non-UTF-8 bytes,
# but we opt into the feature to stay robust against unexpected responses.
base64 = "0.22"
tokio = { version = "1", features = ["rt-multi-thread", "process", "sync", "time", "net"] }
tokio-util = { version = "0.7", features = ["rt"] }
# WebSocket client + server for two uses:
# - Client: Chrome DevTools Protocol connections to the embedded CEF
#   instance over `--remote-debugging-port=9222` (IndexedDB reads,
#   `Runtime.evaluate` for the WhatsApp recipe, DOMSnapshot / Network
#   calls for the Gmail connector).
# - Server: the `webview_apis` bridge at 127.0.0.1 that accepts
#   JSON-RPC frames from the core sidecar so core-side handlers can
#   reach the live-webview connectors via CDP.
tokio-tungstenite = { version = "0.24", default-features = false, features = ["connect", "handshake"] }
url = "2"
futures-util = { version = "0.3", default-features = false, features = ["sink", "std"] }

reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
rand = "0.9"
hex = "0.4"
# Tauri's vendored dev-server proxy (see `vendor/tauri-cef/.../protocol/tauri.rs`)
# builds a reqwest 0.13 client that requires a process-wide rustls
# `CryptoProvider`. Without one, `ClientBuilder::build()` panics with
# "No provider set" the first time `tauri dev` proxies a request. We install
# the ring provider at startup in `lib.rs::run()`.
rustls = { version = "0.23", default-features = false, features = ["ring"] }
log = "0.4"
env_logger = "0.11"

# Sentry for the Tauri shell (desktop host) process — separate Sentry project
# from the React frontend and the Rust core sidecar. DSN is baked at compile
# time via `option_env!("OPENHUMAN_TAURI_SENTRY_DSN")` in `lib.rs::run()` and
# can be overridden at runtime via the same env var. Feature set mirrors the
# core sidecar (`Cargo.toml` at repo root) minus `tracing` since the shell
# uses `log` + `env_logger`.
sentry = { version = "0.47.0", default-features = false, features = ["backtrace", "contexts", "panic", "debug-images", "reqwest", "rustls"] }

# Used by the imessage_scanner module.
anyhow = "1.0"
parking_lot = "0.12"
chrono = "0.4"
async-trait = "0.1"
# Mascot fake-camera pipeline (meet_call): rasterizes the OpenHuman
# mascot SVG to a PNG once, converts it to a YUV420 Y4M frame, and
# points CEF's `--use-file-for-fake-video-capture` flag at the cached
# file so Meet sees the mascot as the agent's webcam. Pure Rust, no
# system codecs needed.
resvg = { version = "0.45", default-features = false, features = ["text", "system-fonts"] }
tiny-skia = "0.11"
# CEF + tauri-runtime-cef dependencies (always required).
# `tauri-runtime-cef::notification::register` is how we hook native Web
# Notification interception per webview, and `cef::Browser` is what we downcast
# from the boxed handle returned by `Webview::with_webview`. tauri-runtime-cef
# isn't published to crates.io — we vendor the whole tauri fork as a submodule
# at `vendor/tauri-cef` and reference the crate by path.
tauri-runtime-cef = { path = "vendor/tauri-cef/crates/tauri-runtime-cef" }
cef = { version = "=146.4.1", default-features = false }

# Core domain logic, embedded in-process so the core's HTTP/JSON-RPC server
# runs as a tokio task inside the Tauri host. Avoids the orphan-sidecar class
# of bugs (PR #1061: Cmd+Q leaving `openhuman-core` and CEF helpers behind)
# by tying the core's lifetime to the GUI process. The existing port-7788
# probe in `core_process::ensure_running` still attaches to a running
# `openhuman-core run` harness when one is already listening.
openhuman_core = { path = "../..", package = "openhuman", default-features = false }

[target.'cfg(unix)'.dependencies]
nix = { version = "0.29", default-features = false, features = ["signal", "user"] }

[target.'cfg(target_os = "macos")'.dependencies]
objc2 = "0.6"
objc2-app-kit = "0.3.2"
mac-notification-sys = "0.6"
# iMessage scanner reads ~/Library/Messages/chat.db read-only on macOS.
rusqlite = { version = "0.37", features = ["bundled"] }
objc2-user-notifications = "0.3.2"
block2 = "0.6.2"
objc2-foundation = { version = "0.3.2", features = ["NSTimer", "block2"] }
# Native WKWebView host for the floating mascot window — bypasses CEF
# (which can't render transparent windowed-mode browsers).
objc2-web-kit = { version = "0.3.2", features = ["block2"] }

[target.'cfg(target_os = "linux")'.dependencies]
notify-rust = { version = "4", default-features = false, features = ["dbus"] }

[target.'cfg(target_os = "windows")'.dependencies]
# AttachConsole — re-attach to the parent shell when the binary runs as a CLI
# (the `core` subcommand). The main binary itself is windows-subsystem so
# launching the Tauri app from Explorer does not pop a console; the helper
# CEF subprocess re-execs inherit that same subsystem.
windows-sys = { version = "0.59", features = [
    "Win32_System_Console",
    "Win32_Foundation",
    # EnumWindows / ShowWindow / SW_HIDE / SW_SHOW used by the main-window
    # close handler. tauri-runtime-cef's window.hide() / minimize() target a
    # cef::Window internal handle, not the visible Chrome_WidgetWin_1
    # top-level frame, so we walk the OS window list ourselves (#1607).
    "Win32_UI_WindowsAndMessaging",
    # CreateMutexW / CloseHandle — used by the pre-CEF single-instance guard
    # (see run() in lib.rs) that detects a second launch before CefRuntime::init
    # fires (Sentry OPENHUMAN-TAURI-A).
    # Win32_Security is required because CreateMutexW's SECURITY_ATTRIBUTES
    # parameter is gated behind it in windows-sys 0.59.
    "Win32_System_Threading",
    "Win32_Security",
    "Win32_Storage_FileSystem",
    "Win32_System_IO",
    "Win32_System_Pipes",
] }

[features]
default = []
# `custom-protocol` switches Tauri from `devUrl` (vite dev server) to the
# bundled `frontendDist` served via `tauri://localhost`. `cargo tauri build`
# turns this on automatically for release; do not put it in `default` or
# every `pnpm dev:app` will silently load the production bundle. DO NOT REMOVE!!
custom-protocol = ["tauri/custom-protocol"]
sandbox-bubblewrap = []
# Forwarded to the core crate to expose `openhuman.test_reset`. Off by
# default; the E2E build flips it on via `cargo tauri build --features
# e2e-test-support`. See app/scripts/e2e-build.sh.
e2e-test-support = ["openhuman_core/e2e-test-support"]

[patch.crates-io]
# `cargo tauri build` resolves dependencies from this manifest, so the
# workspace-level whisper-rs-sys patch is not applied here. The fork forces
# whisper.cpp to use MSVC's static runtime (/MT), matching CEF and avoiding
# LNK2038/LNK1169 CRT conflicts on Windows.
whisper-rs-sys = { git = "https://github.com/tinyhumansai/whisper-rs-sys.git", branch = "main" }

# CEF support lives on the `feat/cef` branch of tauri-apps/tauri. We carry our
# own fork at tinyhumansai/tauri-cef on `feat/cef-notification-intercept` which
# adds native Web Notifications interception — `tauri-runtime-cef::notification`
# (browser-process callback registry) plus `cef-helper` patching `window.Notification`
# and `ServiceWorkerRegistration.prototype.showNotification` from the renderer
# side. The fork is vendored as a git submodule at `vendor/tauri-cef`; the
# submodule's recorded commit is the pin.
#
# Plugins still patch from upstream tauri-apps/plugins-workspace@feat/cef — the
# fork is tauri-only.
tauri = { path = "vendor/tauri-cef/crates/tauri" }
tauri-build = { path = "vendor/tauri-cef/crates/tauri-build" }
tauri-utils = { path = "vendor/tauri-cef/crates/tauri-utils" }
tauri-macros = { path = "vendor/tauri-cef/crates/tauri-macros" }
tauri-runtime = { path = "vendor/tauri-cef/crates/tauri-runtime" }
tauri-runtime-wry = { path = "vendor/tauri-cef/crates/tauri-runtime-wry" }
tauri-plugin = { path = "vendor/tauri-cef/crates/tauri-plugin" }

# Pinned to a specific commit on plugins-workspace@feat/cef so fresh
# dependency resolution (without Cargo.lock) is reproducible and doesn't
# silently drift when upstream pushes to the branch.
tauri-plugin-opener = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "c6561ab6b4f9e7f650d4fc8c53fd8acc9b65b9b2" }
tauri-plugin-deep-link = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "c6561ab6b4f9e7f650d4fc8c53fd8acc9b65b9b2" }
tauri-plugin-global-shortcut = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "c6561ab6b4f9e7f650d4fc8c53fd8acc9b65b9b2" }
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "c6561ab6b4f9e7f650d4fc8c53fd8acc9b65b9b2" }
tauri-plugin-notification = { path = "vendor/tauri-plugin-notification" }

[dev-dependencies]
# `test-util` enables `#[tokio::test(start_paused = true)]` for the
# idle-watchdog unit tests in `cdp/session.rs` (#1213).
tokio = { version = "1", features = ["macros", "rt", "test-util"] }
tempfile = "3"

# Emit just enough DWARF in release builds for Sentry to symbolicate Rust
# panics + render surrounding source lines. `line-tables-only` keeps the
# binary small (only file+line tables, no full type info) while still
# letting `sentry-cli debug-files upload --include-sources` produce a
# usable `.src.zip`. `split-debuginfo = "packed"` writes the debug data
# into a separate `.dSYM` bundle on macOS so the shipped executable
# itself stays slim.
[profile.release]
debug = "line-tables-only"
split-debuginfo = "packed"

# Fast CI builds: trade runtime perf for compile speed
[profile.ci]
inherits = "release"
opt-level = 1
codegen-units = 16
lto = false
incremental = false
strip = true
debug = false
