fix(windows): stop terminal flood on app launch via GUI subsystem + AttachConsole (#1468)

This commit is contained in:
Steven Enamakel
2026-05-10 23:20:25 -07:00
committed by GitHub
parent 62db85ef0d
commit 838e6fce90
4 changed files with 34 additions and 61 deletions
-59
View File
@@ -1,59 +0,0 @@
---
name: CodeRabbit Retrigger
# Periodically scans open PRs and posts `@coderabbitai review` on any whose
# rate-limit window has elapsed. CodeRabbit ignores comments authored by a
# GitHub App, so this workflow uses a personal access token (`RABBIT_PAT`)
# scoped to the `Review` environment.
on:
schedule:
# Every 20 minutes. CodeRabbit Pro reviews 5 PRs/hr, so this gives
# ~3 ticks per hour — enough to catch elapsed windows without thrashing.
- cron: "*/20 * * * *"
workflow_dispatch:
inputs:
max:
description: "Max retriggers this run (CR Pro = 5/hr)"
required: false
default: "5"
dry_run:
description: "Print what would be done; post nothing"
type: boolean
required: false
default: false
permissions:
contents: read
pull-requests: write
issues: write
concurrency:
group: rabbit-retrigger
cancel-in-progress: false
jobs:
retrigger:
name: Retrigger CodeRabbit
runs-on: ubuntu-22.04
# CodeRabbit ignores `@coderabbitai review` comments posted under a
# GitHub App identity, so this workflow uses a personal access token
# scoped to the `Review` environment instead. Set `RABBIT_PAT` on the
# `Review` environment in repo settings — a fine-grained PAT with
# `pull-requests: write` and `issues: write` on this repo is enough.
environment: Review
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24.x
- name: Run rabbit
env:
GH_TOKEN: ${{ secrets.RABBIT_PAT }}
RABBIT_REPO: ${{ github.repository }}
run: |
set -e
ARGS=(run --max "${{ inputs.max || '5' }}")
if [ "${{ inputs.dry_run }}" = "true" ]; then
ARGS+=(--dry-run)
fi
node scripts/rabbit/cli.mjs "${ARGS[@]}"
+1
View File
@@ -50,6 +50,7 @@ dependencies = [
"tokio-util",
"toml 0.8.2",
"url",
"windows-sys 0.59.0",
]
[[package]]
+7
View File
@@ -141,6 +141,13 @@ 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"] }
[features]
default = []
# `custom-protocol` switches Tauri from `devUrl` (vite dev server) to the
+26 -2
View File
@@ -1,5 +1,10 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
// Always run as the Windows GUI subsystem so launching the Tauri app — and
// every CEF helper subprocess re-exec'd from this binary — does not pop a
// console window. Without this, debug builds default to console-subsystem
// and each CEF role (renderer / GPU / utility) opens its own terminal.
// The `core` CLI subcommand path below re-attaches to the parent shell's
// console at runtime via AttachConsole, so command-line output still works.
#![cfg_attr(target_os = "windows", windows_subsystem = "windows")]
// On the CEF runtime, the main binary is re-exec'd as the renderer / GPU /
// utility helper subprocesses. The `cef_entry_point` macro short-circuits
@@ -11,6 +16,13 @@
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.get(1).map(String::as_str) == Some("core") {
// CLI path: re-attach to the parent shell's console so eprintln!
// output lands in the cmd/PowerShell window the user invoked us
// from. No-op (and harmless) when launched without a parent
// console, e.g. from Explorer.
#[cfg(target_os = "windows")]
attach_parent_console();
if let Err(err) = openhuman::run_core_from_args(&args[2..]) {
eprintln!("core process failed: {err}");
std::process::exit(1);
@@ -20,3 +32,15 @@ fn main() {
openhuman::run()
}
#[cfg(target_os = "windows")]
fn attach_parent_console() {
use windows_sys::Win32::System::Console::{AttachConsole, ATTACH_PARENT_PROCESS};
// SAFETY: AttachConsole has no preconditions beyond a valid PID constant.
// It returns 0 on failure (no parent console / already attached); both
// outcomes are fine for our use — we just won't print anything in that
// case, matching the GUI-launch behavior.
unsafe {
AttachConsole(ATTACH_PARENT_PROCESS);
}
}