@mohak34/opencode-notifier 0.1.27-beta.0 → 0.1.27-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +0 -24
  2. package/dist/index.js +65 -12
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -142,30 +142,6 @@ Or use true/false for both:
142
142
  }
143
143
  ```
144
144
 
145
- ### Event Filtering
146
-
147
- Filter which events trigger notifications entirely. Useful when you only want notifications for specific events (e.g., only when OpenCode needs your input):
148
-
149
- ```json
150
- {
151
- "enabledEvents": ["permission", "question"]
152
- }
153
- ```
154
-
155
- - If `enabledEvents` is not specified or empty, all events are enabled (backward compatible)
156
- - Valid values: `"permission"`, `"complete"`, `"subagent_complete"`, `"error"`, `"question"`, `"interrupted"`
157
- - Events not in the list will not trigger sounds, notifications, or custom commands
158
-
159
- Example: Only notify for permission requests and errors:
160
-
161
- ```json
162
- {
163
- "sound": true,
164
- "notification": true,
165
- "enabledEvents": ["permission", "error"]
166
- }
167
- ```
168
-
169
145
  ### Messages
170
146
 
171
147
  Customize the notification text:
package/dist/index.js CHANGED
@@ -3746,6 +3746,9 @@ var DEFAULT_CONFIG = {
3746
3746
  showSessionTitle: false,
3747
3747
  showIcon: true,
3748
3748
  notificationSystem: "osascript",
3749
+ linux: {
3750
+ grouping: true
3751
+ },
3749
3752
  command: {
3750
3753
  enabled: false,
3751
3754
  path: "",
@@ -3842,6 +3845,9 @@ function loadConfig() {
3842
3845
  showSessionTitle: userConfig.showSessionTitle ?? DEFAULT_CONFIG.showSessionTitle,
3843
3846
  showIcon: userConfig.showIcon ?? DEFAULT_CONFIG.showIcon,
3844
3847
  notificationSystem: userConfig.notificationSystem === "node-notifier" ? "node-notifier" : "osascript",
3848
+ linux: {
3849
+ grouping: typeof userConfig.linux?.grouping === "boolean" ? userConfig.linux.grouping : DEFAULT_CONFIG.linux.grouping
3850
+ },
3845
3851
  command: {
3846
3852
  enabled: typeof userCommand.enabled === "boolean" ? userCommand.enabled : DEFAULT_CONFIG.command.enabled,
3847
3853
  path: typeof userCommand.path === "string" ? userCommand.path : DEFAULT_CONFIG.command.path,
@@ -3891,12 +3897,6 @@ function isEventSoundEnabled(config, event) {
3891
3897
  function isEventNotificationEnabled(config, event) {
3892
3898
  return config.events[event].notification;
3893
3899
  }
3894
- function isEventEnabled(config, event) {
3895
- if (!config.enabledEvents || config.enabledEvents.length === 0) {
3896
- return true;
3897
- }
3898
- return config.enabledEvents.includes(event);
3899
- }
3900
3900
  function getMessage(config, event) {
3901
3901
  return config.messages[event];
3902
3902
  }
@@ -3934,7 +3934,7 @@ function interpolateMessage(message, context) {
3934
3934
  // src/notify.ts
3935
3935
  var import_node_notifier = __toESM(require_node_notifier(), 1);
3936
3936
  import os from "os";
3937
- import { exec } from "child_process";
3937
+ import { exec, execFile } from "child_process";
3938
3938
  var DEBOUNCE_MS = 1000;
3939
3939
  var platform = os.type();
3940
3940
  var platformNotifier;
@@ -3948,7 +3948,53 @@ if (platform === "Linux" || platform.match(/BSD$/)) {
3948
3948
  platformNotifier = import_node_notifier.default;
3949
3949
  }
3950
3950
  var lastNotificationTime = {};
3951
- async function sendNotification(title, message, timeout, iconPath, notificationSystem = "osascript") {
3951
+ var lastLinuxNotificationId = null;
3952
+ var linuxNotifySendSupportsReplace = null;
3953
+ function detectNotifySendCapabilities() {
3954
+ return new Promise((resolve) => {
3955
+ execFile("notify-send", ["--version"], (error, stdout) => {
3956
+ if (error) {
3957
+ resolve(false);
3958
+ return;
3959
+ }
3960
+ const match = stdout.match(/(\d+)\.(\d+)/);
3961
+ if (match) {
3962
+ const major = parseInt(match[1], 10);
3963
+ const minor = parseInt(match[2], 10);
3964
+ resolve(major > 0 || major === 0 && minor >= 8);
3965
+ return;
3966
+ }
3967
+ resolve(false);
3968
+ });
3969
+ });
3970
+ }
3971
+ function sendLinuxNotificationDirect(title, message, timeout, iconPath, grouping = true) {
3972
+ return new Promise((resolve) => {
3973
+ const args = [];
3974
+ if (iconPath) {
3975
+ args.push("--icon", iconPath);
3976
+ }
3977
+ args.push("--expire-time", String(timeout * 1000));
3978
+ args.push("--app-name", "OpenCode");
3979
+ if (grouping && lastLinuxNotificationId !== null) {
3980
+ args.push("--replace-id", String(lastLinuxNotificationId));
3981
+ }
3982
+ if (grouping) {
3983
+ args.push("--print-id");
3984
+ }
3985
+ args.push("--", title, message);
3986
+ execFile("notify-send", args, (error, stdout) => {
3987
+ if (!error && grouping && stdout) {
3988
+ const id = parseInt(stdout.trim(), 10);
3989
+ if (!isNaN(id)) {
3990
+ lastLinuxNotificationId = id;
3991
+ }
3992
+ }
3993
+ resolve();
3994
+ });
3995
+ });
3996
+ }
3997
+ async function sendNotification(title, message, timeout, iconPath, notificationSystem = "osascript", linuxGrouping = true) {
3952
3998
  const now = Date.now();
3953
3999
  if (lastNotificationTime[message] && now - lastNotificationTime[message] < DEBOUNCE_MS) {
3954
4000
  return;
@@ -3976,6 +4022,16 @@ async function sendNotification(title, message, timeout, iconPath, notificationS
3976
4022
  });
3977
4023
  });
3978
4024
  }
4025
+ if (platform === "Linux" || platform.match(/BSD$/)) {
4026
+ if (linuxGrouping) {
4027
+ if (linuxNotifySendSupportsReplace === null) {
4028
+ linuxNotifySendSupportsReplace = await detectNotifySendCapabilities();
4029
+ }
4030
+ if (linuxNotifySendSupportsReplace) {
4031
+ return sendLinuxNotificationDirect(title, message, timeout, iconPath, true);
4032
+ }
4033
+ }
4034
+ }
3979
4035
  return new Promise((resolve) => {
3980
4036
  const notificationOptions = {
3981
4037
  title,
@@ -4166,9 +4222,6 @@ function getNotificationTitle(config, projectName) {
4166
4222
  return "OpenCode";
4167
4223
  }
4168
4224
  async function handleEvent(config, eventType, projectName, elapsedSeconds, sessionTitle) {
4169
- if (!isEventEnabled(config, eventType)) {
4170
- return;
4171
- }
4172
4225
  const promises = [];
4173
4226
  const rawMessage = getMessage(config, eventType);
4174
4227
  const message = interpolateMessage(rawMessage, {
@@ -4178,7 +4231,7 @@ async function handleEvent(config, eventType, projectName, elapsedSeconds, sessi
4178
4231
  if (isEventNotificationEnabled(config, eventType)) {
4179
4232
  const title = getNotificationTitle(config, projectName);
4180
4233
  const iconPath = getIconPath(config);
4181
- promises.push(sendNotification(title, message, config.timeout, iconPath, config.notificationSystem));
4234
+ promises.push(sendNotification(title, message, config.timeout, iconPath, config.notificationSystem, config.linux.grouping));
4182
4235
  }
4183
4236
  if (isEventSoundEnabled(config, eventType)) {
4184
4237
  const customSoundPath = getSoundPath(config, eventType);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohak34/opencode-notifier",
3
- "version": "0.1.27-beta.0",
3
+ "version": "0.1.27-beta.2",
4
4
  "description": "OpenCode plugin that sends system notifications and plays sounds when permission is needed, generation completes, or errors occur",
5
5
  "author": "mohak34",
6
6
  "license": "MIT",