fix(desktop): render connection screen via custom URI scheme (closes #3052)#3056
Merged
Conversation
The connection screen was loaded via about:blank and the HTML injected
through window.eval("document.open/write/close"). WebKitGTK 2.50 (stock
NixOS, current AppImage bundle) silently no-ops that sequence, so new
users hit a blank window on every first launch — they can't pick local
or remote, the app is dead.
Serve the HTML through a registered custom URI scheme (lfconnect://) and
point the webview at that instead. This is a normal navigation to a
normal HTTP response, so WebKit loads it like any other page.
Also restore libayatana-appindicator to desktopBuildInputs plus a
postFixup patchelf for its rpath. tray-icon dlopens the library at
runtime, not as a link dep, so without this the nix-built desktop
binary aborts on launch.
Merged
6 tasks
houko
added a commit
that referenced
this pull request
Apr 26, 2026
PR review caught 1 stale-doc contradiction + 7 undocumented behaviour changes from the fix-PR cohort. - #3114 — configuration/core: 'api_key empty = unauthenticated' was stale; now documents the loopback-only policy (non-loopback bypass was closed) - #3170 — features/observability: auto_start is opt-in; home_dir- scoped Docker labels; RAII cleanup - #2989 — api/agents POST /message: per-request session_id override - #3048 — Interrupting a Running Agent Turn: /stop cascades into agent_send subagents (recursive) - #3056 + #3000 — desktop: dedicated Connection screen via custom URI scheme with retry / open-in-browser / uninstall - #2952 — triggers: response routes to agent's home channel - #2955 — triggers: task_posted assignee_match = 'self' | 'any' - #3069 — providers/local: 60-second reprobe + manual 'Test connection' refresh All sections mirrored in docs/src/app/zh/.
houko
added a commit
that referenced
this pull request
Apr 26, 2026
…pi / observability (#3189) * docs(providers): add Novita / SearXHG / Bedrock entries * docs(config): document [parallel_tools] section + max_history_messages * docs(scheduler): cron multi-delivery + pre_script + silent_marker * docs: live context.md, chat attachments, CLI slash commands Salvages three of the six items from the (quota-killed) misc-features agent run. Each is a focused append, no rewrite of existing content. - agent/templates: live Live Context section explains the per-turn re-read of `context.md` (#3115), the .identity/ vs root path lookup, the 32 KB cap with stale-cache fallback, and the cache_context opt-out. - integrations/api/agents: attachment-resolution table (image / PDF / text+code) covering the supported MIME / extension list and the 200 KB truncation, plus a note about adjacent-text coalescing for small chat-tuned local models (#3094). - integrations/cli/commands: 'Slash Commands in Chat' section listing the registry-backed CLI commands (/model /status /help /clear /kill /exit) and pointing at channel-side commands for the broader set (#3122 #3123). * docs: tool invoke API, trajectory export, doctor audit, CLI default-pick, SDK codegen Picks up the items the second misc-features agent didn't get to before hitting the org quota. - integrations/api/system: POST /api/tools/{name}/invoke (#3025) — fail- closed allowlist, agent_id requirement for approval-gated tools. - integrations/api/agents: GET /sessions/{id}/trajectory (#3097) — json/jsonl formats, redactor pipeline, audit use case. - operations/troubleshooting: 'Audit checks' subsection enumerating the three registered AuditChecks (#3082) — VaultKey, ApiListenAddr, ConfigTomlSchema — with what each asserts and how to extend. - configuration/providers/tools: 'CLI logins as first-class default providers' section (#3061) — detection priority claude-code > codex- cli > gemini-cli > qwen-code, override via [default_model] in config.toml. - integrations/sdk: 'Auto-generated from openapi.json' section (#3046) — scripts/codegen-sdks.py, pre-commit hook, openai-tag skip rule. * docs(zh): mirror providers / config-core / cron / features-index sections * docs(zh): mirror agent / api / cli / providers-tools / troubleshooting / sdk additions Round 2 of the zh translation pass — picks up the seven mid-priority files that the first commit didn't cover. All sections mirror the EN content from #3189 but read naturally as Chinese (terms like agent / session / fallback / NoEntry left in English where they're API surface, prose translated to 中文). - agent/templates: Live Context section, .identity/ vs root fallback, cache_context = true opt-out. - api/agents: attachment-resolution table + trajectory export endpoint (#3025 / #3094 / #3097). - api/system: POST /api/tools/{name}/invoke endpoint + fail-closed allowlist explanation. - cli/commands: 'Slash Commands in Chat' section listing CLI registry commands and pointing at channel commands. - providers/tools: 'CLI logins as first-class default providers' detection priority and override. - troubleshooting: 'Audit checks' subsection + table. - sdk: 'Auto-generated from openapi.json' section. * docs: refresh /new slash-command semantics (#3071 review fix) PR review on #3189 (houko) caught two stale references describing the pre-#3071 behavior of /new ('wipe the session' / 'clear history'). The new semantics fork off a fresh session while the previous one stays resumable on the same channel — phrasing updated in 4 places (en + zh × 2 files), plus a one-line clarifier in the slash-command roster section so the cross-reference doesn't silently inherit the old mental model: - configuration/channels: 'wipe the session' → 'fork off into a new session (the prior conversation stays resumable on the channel)' - integrations/api/realtime: '(clear history)' → 'forks into a fresh session — the prior session is preserved and remains resumable' - integrations/cli/commands roster paragraph: explicit note that /new is a fork, not a wipe. Same wording mirrored to docs/src/app/zh/. * docs(channels): 9 channel-related Apr 22-25 PRs (en + zh) Covers the channel + bridge feature wave: - #3020 per-agent ChannelOverrides — fixes the contradicting 'without modifying the agent manifest' phrasing in both en and zh. - #3077 prefix_agent_name + Signal plain-text default - #3009 Slack reactions_enabled + #3005 Feishu @mention preservation consolidated into a 'Reactions and Processing State' section - #3008 Signal media attachments - #3012 WhatsApp send_voice + dm_policy / group_policy - #3011 Webhook deliver_only mode - #2972 channel file downloads (file_download_dir / max_bytes config) * docs(config-core): provider timeout / browser CDP / cron session caps (en + zh) Three new `config.toml` sections that landed Apr 22-23: - #3004 `[provider_request_timeout_secs]` map - #2993 / #2991 `[browser].cdp_endpoint` + `cdp_auth_token_env` - #2994 `[kernel].cron_session_max_tokens` / `cron_session_max_messages` * docs(api): GET /attach + Owner Notice envelope (en + zh) - #3078 SSE attach endpoint for multi-client co-watching — describes the per-session SessionStreamHub fan-out, attacher behaviour, and the curl example. - #2965 ReplyEnvelope.owner_notice + notify_owner tool — message body field, StreamEvent variant, WhatsApp OWNER_JIDS fan-out. * docs(observability + ops): Tempo stack, cache_hit_ratio metric, daemon log tee (en + zh) - #3064 + #3149 — bundled observability stack (otel-collector / Tempo / Grafana), bring-up commands, [telemetry] config, business spans, cache_hit_ratio metric formula and where it surfaces - #3022 — `librefang start --foreground` now tees logs to ~/.librefang/logs/daemon-YYYY-MM-DD.log; same-day append; 7-day rotation pruned on daemon start * docs: hooks transform / lazy tools / mcp taint / capability detection / providers extras Final batch of catch-up docs covering the remaining Apr 22-25 user-facing features: - agent/hooks: transform_tool_result hook contract (#3003) - agent/templates: tool_search / tool_load lazy loading + lazy_tools opt-out (#3047) - integrations/mcp-a2a: TaintRuleId enum + per-tool skip_rules policy (#2999) - configuration/features: compaction summaries in user's conversation language (#3007) - configuration/providers/local: embedding auto-detection priority list (#3099) + Ollama capability detection (Modality / metadata pipeline, #3074 / #3133 / #3134 / #3140) - configuration/providers/management: custom image-gen provider via generic OpenAI-compat driver (#2998) + Moonshot file-upload helper via /v1/files (#2966) All sections mirrored to docs/src/app/zh/. * docs: address houko fix-PR audit (8 items, en + zh) PR review caught 1 stale-doc contradiction + 7 undocumented behaviour changes from the fix-PR cohort. - #3114 — configuration/core: 'api_key empty = unauthenticated' was stale; now documents the loopback-only policy (non-loopback bypass was closed) - #3170 — features/observability: auto_start is opt-in; home_dir- scoped Docker labels; RAII cleanup - #2989 — api/agents POST /message: per-request session_id override - #3048 — Interrupting a Running Agent Turn: /stop cascades into agent_send subagents (recursive) - #3056 + #3000 — desktop: dedicated Connection screen via custom URI scheme with retry / open-in-browser / uninstall - #2952 — triggers: response routes to agent's home channel - #2955 — triggers: task_posted assignee_match = 'self' | 'any' - #3069 — providers/local: 60-second reprobe + manual 'Test connection' refresh All sections mirrored in docs/src/app/zh/.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #3052 — first-launch blank window on Linux desktop.
Two fixes bundled because they're both hit by the same user flow (fresh NixOS build, first launch):
1. Connection screen no longer renders (the primary bug)
crates/librefang-desktop/src/lib.rsbuilt the first-launch connection screen by openingabout:blankand injecting HTML viawindow.eval(\"document.open(); document.write(...); document.close();\"). On WebKitGTK 2.50 — stock NixOS 25.11 / 26.05, and the webkit bundled in the AppImage — that sequence silently no-ops. The window opens, the title says "LibreFang — Connect", and the content area stays blank. New users (no saved preference, noLIBREFANG_SERVER_URL) always take this path, so the app is dead on arrival.Fix: register a custom URI scheme (
lfconnect://) on the TauriBuilder, return the connection HTML as a normal HTTP response, and point the webview atlfconnect://localhost/viaWebviewUrl::CustomProtocol. That's a regular navigation to a regular response, so WebKit loads it the same way it loads any other page — noabout:blankedge cases, no async eval race, andconnect_remote/start_localstill work viawindow.location.href = ….2. Nix build runs but the binary panics on launch
#2974 merged the build-organisation part of a flake fix but dropped the libayatana-appindicator bits. Since
tray-icondlopenslibayatana-appindicator3.so.1at runtime (it's not a link-time dep), the resulting binary aborts on first launch on stock NixOS. This is the "build is again failing due to the dlopen not finding libayatana-appindicator" half of #3052.Restored the two lines from commit
cdad334ein the original PR branch: add the lib todesktopBuildInputs, and apostFixupthat patches it into the desktop binary's RPATH.Verification (on NixOS 25.11 + GNOME 49, WebKitGTK 2.50.5)
cargo check -p librefang-desktop✅ cleancargo clippy -p librefang-desktop -- -D warnings✅ cleannix build .#librefang-desktop✅ builds and produces a runnable binaryNotes / follow-ups
connection.rs) — thewaitForTauri()polling that was there for the old about:blank timing is harmless on the new path and I'd rather not scope-creep this PR.lfconnect://localhost; Tauri IPC (__TAURI__.core.invoke) works from it the same as fromhttp://127.0.0.1, so the existingtest_connection/connect_remote/start_localcommands don't need any changes.