Skip to content

Commit ce510f2

Browse files
authored
Merge pull request #895 from assembledev/fix/linux-notification-actions
fix(linux): preserve actions in approval notifications
2 parents eb057a0 + 1cdba32 commit ce510f2

16 files changed

Lines changed: 1002 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
3535

3636
### Fixed
3737

38+
- Approval notifications now preserve the upstream Approve, Approve for
39+
session, and Decline actions on Linux. A small freedesktop notification
40+
bridge forwards the action and close signals that Electron's Linux
41+
notification backend does not expose, with the existing View-only Electron
42+
notification retained as a fail-soft fallback.
3843
- Remote mobile cold starts now select one runtime owner deterministically.
3944
Explicit systemd user-service configuration takes precedence over the
4045
Desktop app-server and standalone fallback, while a versioned Desktop marker

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
[workspace]
2-
members = ["computer-use-linux", "read-aloud-linux", "updater", "record-replay-linux"]
2+
members = [
3+
"computer-use-linux",
4+
"notification-actions-linux",
5+
"read-aloud-linux",
6+
"updater",
7+
"record-replay-linux",
8+
]
39
resolver = "2"

docs/agents/repository-map.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ The updater runs unprivileged and only escalates through `pkexec` for
220220

221221
## Computer Use, Browser, Read Aloud, And Record & Replay
222222

223+
- `notification-actions-linux/`
224+
Small Rust D-Bus bridge for freedesktop notification action and close
225+
signals. The main-process core patch uses it only for upstream notifications
226+
that already carry actions and falls back to Electron otherwise.
223227
- `computer-use-linux/`
224228
Rust crate for Linux Computer Use MCP, Chrome native messaging host, and the
225229
COSMIC helper. It covers input, capture, accessibility, terminal, identity,

flake.nix

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@
7575
cp -R ${./computer-use-linux} "$out/computer-use-linux"
7676
chmod -R u+w "$out"
7777
'';
78+
notificationActionsBuildSource = pkgs.runCommandLocal "codex-notification-actions-linux-source" { } ''
79+
mkdir -p "$out"
80+
cp ${./Cargo.lock} "$out/Cargo.lock"
81+
cat > "$out/Cargo.toml" <<'EOF'
82+
[workspace]
83+
members = ["notification-actions-linux"]
84+
resolver = "2"
85+
EOF
86+
cp -R ${./notification-actions-linux} "$out/notification-actions-linux"
87+
chmod -R u+w "$out"
88+
'';
7889
nativeModulesBuildSupport = pkgs.runCommandLocal "codex-native-modules-build-support" { } ''
7990
mkdir -p "$out/scripts/lib"
8091
cp ${./scripts/lib/native-modules.sh} "$out/scripts/lib/native-modules.sh"
@@ -161,6 +172,33 @@
161172
'';
162173
};
163174

175+
codexNotificationActionsBinary = pkgs.rustPlatform.buildRustPackage {
176+
pname = "codex-notification-actions-linux";
177+
version = "0.1.0";
178+
src = notificationActionsBuildSource;
179+
180+
cargoLock = {
181+
lockFile = ./Cargo.lock;
182+
};
183+
184+
cargoBuildFlags = [
185+
"-p"
186+
"codex-notification-actions-linux"
187+
];
188+
189+
doCheck = true;
190+
191+
installPhase = ''
192+
runHook preInstall
193+
release_dir="target/''${CARGO_BUILD_TARGET:-${pkgs.stdenv.hostPlatform.rust.rustcTarget}}/release"
194+
if [ ! -d "$release_dir" ]; then
195+
release_dir="target/release"
196+
fi
197+
install -Dm0755 "$release_dir/codex-notification-actions-linux" "$out/bin/codex-notification-actions-linux"
198+
runHook postInstall
199+
'';
200+
};
201+
164202
codexMcpHelperReaper = pkgs.rustPlatform.buildRustPackage {
165203
pname = "codex-mcp-helper-reaper";
166204
version = "0.1.0";
@@ -497,6 +535,7 @@ PY
497535
export CODEX_LINUX_COMPUTER_USE_BACKEND_SOURCE="${codexComputerUseBinaries}/bin/codex-computer-use-linux"
498536
export CODEX_LINUX_COMPUTER_USE_COSMIC_SOURCE="${codexComputerUseBinaries}/bin/codex-computer-use-cosmic"
499537
export CODEX_CHROME_EXTENSION_HOST_SOURCE="${codexComputerUseBinaries}/bin/codex-chrome-extension-host"
538+
export CODEX_NOTIFICATION_ACTIONS_SOURCE="${codexNotificationActionsBinary}/bin/codex-notification-actions-linux"
500539
${pkgs.lib.optionalString (builtins.elem "mcp-helper-reaper" linuxFeatureIds) ''
501540
export CODEX_MCP_HELPER_REAPER_SOURCE="${codexMcpHelperReaper}/bin/codex-mcp-helper-reaper"
502541
''}
@@ -700,6 +739,7 @@ PY
700739
cd "$source_dir"
701740
export CODEX_INSTALL_DIR="''${CODEX_INSTALL_DIR:-$root_dir/codex-app}"
702741
export CODEX_MANAGED_NODE_SOURCE="${pkgs.nodejs}"
742+
export CODEX_NOTIFICATION_ACTIONS_SOURCE="${codexNotificationActionsBinary}/bin/codex-notification-actions-linux"
703743
${pkgs.bash}/bin/bash "$source_dir/install.sh" "$source_dir/Codex.dmg" "$@"
704744
705745
install_dir="''${CODEX_INSTALL_DIR:-$root_dir/codex-app}"
@@ -719,6 +759,11 @@ PY
719759
};
720760

721761
checks = {
762+
notification-actions-linux = codexNotificationActionsBinary;
763+
notification-actions-installer = pkgs.runCommand "codex-notification-actions-installer-check" { } ''
764+
grep -F 'CODEX_NOTIFICATION_ACTIONS_SOURCE=' ${installer}/bin/codex-desktop-installer >/dev/null
765+
touch "$out"
766+
'';
722767
nix-linux-features-evaluation = import ./nix/linux-features-test.nix {
723768
inherit pkgs self system;
724769
};

install.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ LINUX_ICON_SOURCE="${CODEX_LINUX_ICON_SOURCE:-}"
3636
. "$SCRIPT_DIR/scripts/lib/asar-patch.sh"
3737
. "$SCRIPT_DIR/scripts/lib/webview-install.sh"
3838
. "$SCRIPT_DIR/scripts/lib/bundled-plugins.sh"
39+
. "$SCRIPT_DIR/scripts/lib/notification-actions.sh"
3940
. "$SCRIPT_DIR/scripts/lib/linux-features.sh"
4041
. "$SCRIPT_DIR/scripts/lib/rebuild-report.sh"
4142
. "$SCRIPT_DIR/scripts/lib/build-info.sh"
@@ -341,6 +342,7 @@ main() {
341342
download_electron
342343
extract_webview "$app_dir"
343344
install_app
345+
stage_linux_notification_actions_bridge
344346
install_bundled_plugin_resources "$app_dir"
345347
run_linux_feature_stage_hooks "$app_dir"
346348
create_start_script
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "codex-notification-actions-linux"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[[bin]]
7+
name = "codex-notification-actions-linux"
8+
path = "src/main.rs"
9+
10+
[dependencies]
11+
anyhow = "1.0.102"
12+
futures-util = "0.3.32"
13+
serde = { version = "1.0.228", features = ["derive"] }
14+
serde_json = "1.0.149"
15+
tokio = { version = "1.51.1", features = ["io-std", "io-util", "macros", "rt"] }
16+
zbus = "5.14.0"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Linux Notification Actions Bridge
2+
3+
`codex-notification-actions-linux` bridges the action-bearing notification
4+
payload already produced by Codex Desktop to the freedesktop
5+
`org.freedesktop.Notifications` interface. Electron exposes notification action
6+
buttons on macOS and Windows but not Linux, even when the active Linux
7+
notification server advertises the standard `actions` capability.
8+
9+
The Electron main-process patch starts one short-lived bridge process per
10+
actionable notification. The bridge accepts one JSON request on stdin, sends JSON events
11+
for show, click, action, and close on stdout, and accepts `close` on stdin. It
12+
does not execute commands or make approval decisions; it returns only the
13+
selected action index to the existing upstream notification callback.
14+
15+
If the session bus or notification server is unavailable, or the server does
16+
not advertise action support, the bridge reports `unavailable` and the app
17+
uses its existing Electron notification instead.
18+
19+
Run its tests from the repository root:
20+
21+
```bash
22+
cargo test -p codex-notification-actions-linux
23+
```

0 commit comments

Comments
 (0)