@mohak34/opencode-notifier 0.1.17 → 0.1.18-beta.1
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.
- package/README.md +0 -10
- package/dist/index.js +22 -330
- package/logos/opencode-logo-dark.png +0 -0
- package/logos/opencode-logo-light.png +0 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -92,7 +92,6 @@ To customize the plugin, create `~/.config/opencode/opencode-notifier.json`:
|
|
|
92
92
|
"notification": true,
|
|
93
93
|
"timeout": 5,
|
|
94
94
|
"showProjectName": true,
|
|
95
|
-
"suppressWhenFocused": false,
|
|
96
95
|
"command": {
|
|
97
96
|
"enabled": false,
|
|
98
97
|
"path": "/path/to/command",
|
|
@@ -131,7 +130,6 @@ To customize the plugin, create `~/.config/opencode/opencode-notifier.json`:
|
|
|
131
130
|
| `notification` | boolean | `true` | Global toggle for all notifications |
|
|
132
131
|
| `timeout` | number | `5` | Notification duration in seconds (Linux only) |
|
|
133
132
|
| `showProjectName` | boolean | `true` | Show project folder name in notification title |
|
|
134
|
-
| `suppressWhenFocused` | boolean | `false` | Suppress notifications when terminal is focused |
|
|
135
133
|
| `command` | object | — | Command execution settings (enabled/path/args/minDuration) |
|
|
136
134
|
|
|
137
135
|
### Events
|
|
@@ -166,14 +164,6 @@ Or use a boolean to toggle both:
|
|
|
166
164
|
|
|
167
165
|
Note: `complete` fires for primary (main) session completion, while `subagent_complete` fires for subagent completion. `subagent_complete` defaults to disabled (both sound and notification are false).
|
|
168
166
|
|
|
169
|
-
### Suppress when focused
|
|
170
|
-
|
|
171
|
-
When `suppressWhenFocused` is enabled, notifications are skipped if your terminal is the frontmost window.
|
|
172
|
-
|
|
173
|
-
- macOS: works out of the box
|
|
174
|
-
- Windows: uses PowerShell to detect the foreground app
|
|
175
|
-
- Linux: focus suppression is disabled (Wayland/X11 focus detection is unreliable)
|
|
176
|
-
|
|
177
167
|
### Messages
|
|
178
168
|
|
|
179
169
|
Customize notification text:
|
package/dist/index.js
CHANGED
|
@@ -18,231 +18,6 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
18
18
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
19
19
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
20
20
|
|
|
21
|
-
// node_modules/detect-terminal/dist/index.js
|
|
22
|
-
var require_dist = __commonJS((exports, module) => {
|
|
23
|
-
var __create2 = Object.create;
|
|
24
|
-
var __defProp2 = Object.defineProperty;
|
|
25
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
26
|
-
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
27
|
-
var __getProtoOf2 = Object.getPrototypeOf;
|
|
28
|
-
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
29
|
-
var __name = (target, value) => __defProp2(target, "name", { value, configurable: true });
|
|
30
|
-
var __export = (target, all) => {
|
|
31
|
-
for (var name in all)
|
|
32
|
-
__defProp2(target, name, { get: all[name], enumerable: true });
|
|
33
|
-
};
|
|
34
|
-
var __copyProps = (to, from, except, desc) => {
|
|
35
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
36
|
-
for (let key of __getOwnPropNames2(from))
|
|
37
|
-
if (!__hasOwnProp2.call(to, key) && key !== except)
|
|
38
|
-
__defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
39
|
-
}
|
|
40
|
-
return to;
|
|
41
|
-
};
|
|
42
|
-
var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target, mod));
|
|
43
|
-
var __toCommonJS = (mod) => __copyProps(__defProp2({}, "__esModule", { value: true }), mod);
|
|
44
|
-
var detect_terminal_exports = {};
|
|
45
|
-
__export(detect_terminal_exports, {
|
|
46
|
-
default: () => detect_terminal_default,
|
|
47
|
-
detectFromEnv: () => detectFromEnv,
|
|
48
|
-
detectFromProcessTitle: () => detectFromProcessTitle,
|
|
49
|
-
detectFromShell: () => detectFromShell,
|
|
50
|
-
detectTerminal: () => detectTerminal
|
|
51
|
-
});
|
|
52
|
-
module.exports = __toCommonJS(detect_terminal_exports);
|
|
53
|
-
var import_node_child_process = __require("child_process");
|
|
54
|
-
var import_node_path = __toESM2(__require("path"));
|
|
55
|
-
var detectFromEnv = /* @__PURE__ */ __name(() => {
|
|
56
|
-
const platform = process.platform;
|
|
57
|
-
if (platform === "android" && process.env.TERMUX_VERSION) {
|
|
58
|
-
return "termux";
|
|
59
|
-
}
|
|
60
|
-
let termProgram = process.env.TERM_PROGRAM?.trim()?.toLowerCase();
|
|
61
|
-
if (platform === "darwin" && termProgram) {
|
|
62
|
-
termProgram = import_node_path.default.parse(termProgram).name;
|
|
63
|
-
}
|
|
64
|
-
if (termProgram) {
|
|
65
|
-
switch (termProgram) {
|
|
66
|
-
case "apple_terminal":
|
|
67
|
-
return "terminal";
|
|
68
|
-
case "eterm":
|
|
69
|
-
return "eterm";
|
|
70
|
-
case "gnome-terminal":
|
|
71
|
-
return "gnome_terminal";
|
|
72
|
-
case "gnome-terminal-server":
|
|
73
|
-
return "gnome_terminal";
|
|
74
|
-
case "hyper":
|
|
75
|
-
return "hyper";
|
|
76
|
-
case "iterm.app":
|
|
77
|
-
return "iterm";
|
|
78
|
-
case "iterm":
|
|
79
|
-
return "iterm";
|
|
80
|
-
case "iterm2":
|
|
81
|
-
return "iterm";
|
|
82
|
-
case "kitty":
|
|
83
|
-
return "kitty";
|
|
84
|
-
case "konsole":
|
|
85
|
-
return "konsole";
|
|
86
|
-
case "mate-terminal":
|
|
87
|
-
return "mate_terminal";
|
|
88
|
-
case "powershell":
|
|
89
|
-
return "powershell";
|
|
90
|
-
case "putty":
|
|
91
|
-
return "putty";
|
|
92
|
-
case "qterminal":
|
|
93
|
-
return "qterminal";
|
|
94
|
-
case "rxvt":
|
|
95
|
-
return "rxvt";
|
|
96
|
-
case "terminal.app":
|
|
97
|
-
return "terminal_app";
|
|
98
|
-
case "terminal":
|
|
99
|
-
return "terminal";
|
|
100
|
-
case "terminator":
|
|
101
|
-
return "terminator";
|
|
102
|
-
case "termux":
|
|
103
|
-
return "termux";
|
|
104
|
-
case "vscode":
|
|
105
|
-
return "vscode";
|
|
106
|
-
case "warp":
|
|
107
|
-
return "warp";
|
|
108
|
-
case "wezterm":
|
|
109
|
-
return "wezterm";
|
|
110
|
-
case "xfce4-terminal":
|
|
111
|
-
return "xfce4_terminal";
|
|
112
|
-
case "alacritty":
|
|
113
|
-
return "alacritty";
|
|
114
|
-
default:
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
return termProgram.replace(/[^a-z0-9]+/g, "_");
|
|
118
|
-
}
|
|
119
|
-
if (typeof process.env.VSCODE_PID !== "undefined" || typeof process.env.TERM_PROGRAM_VERSION !== "undefined" && /vscode/i.test(process.env.TERM_PROGRAM_VERSION)) {
|
|
120
|
-
return "vscode";
|
|
121
|
-
}
|
|
122
|
-
const term = process.env.TERM?.trim()?.toLowerCase();
|
|
123
|
-
if (term && term !== "unknown") {
|
|
124
|
-
if (term === "xterm" || term === "xterm-256color") {
|
|
125
|
-
if (process.env.VTE_VERSION) {
|
|
126
|
-
const vteVersion = parseInt(process.env.VTE_VERSION, 10);
|
|
127
|
-
if (vteVersion >= 3803) {
|
|
128
|
-
return "gnome_terminal";
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
for (const [key] of Object.entries(process.env)) {
|
|
132
|
-
if (/konsole/i.test(key)) {
|
|
133
|
-
return "konsole";
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (platform === "darwin") {
|
|
137
|
-
return "terminal";
|
|
138
|
-
}
|
|
139
|
-
return "xterm";
|
|
140
|
-
}
|
|
141
|
-
if (/screen/.test(term))
|
|
142
|
-
return "screen";
|
|
143
|
-
if (/tmux/.test(term))
|
|
144
|
-
return "tmux";
|
|
145
|
-
if (/rxvt/.test(term))
|
|
146
|
-
return "rxvt";
|
|
147
|
-
if (/vt100/.test(term))
|
|
148
|
-
return "vt100";
|
|
149
|
-
if (/linux/.test(term))
|
|
150
|
-
return "linux_console";
|
|
151
|
-
if (/alacritty/.test(term))
|
|
152
|
-
return "alacritty";
|
|
153
|
-
if (/dopamine/.test(term))
|
|
154
|
-
return "dopamine";
|
|
155
|
-
if (/kitty/.test(term))
|
|
156
|
-
return "kitty";
|
|
157
|
-
if (/ghostty/.test(term))
|
|
158
|
-
return "ghostty";
|
|
159
|
-
return term.replace(/[^a-z0-9]+/g, "_");
|
|
160
|
-
}
|
|
161
|
-
const colorTerm = process.env.COLORTERM?.trim()?.toLowerCase();
|
|
162
|
-
if (colorTerm === "truecolor" || colorTerm === "24bit") {
|
|
163
|
-
return "truecolor_terminal";
|
|
164
|
-
}
|
|
165
|
-
if (colorTerm) {
|
|
166
|
-
return colorTerm.replace(/[^a-z0-9]+/g, "_");
|
|
167
|
-
}
|
|
168
|
-
return null;
|
|
169
|
-
}, "detectFromEnv");
|
|
170
|
-
var detectFromShell = /* @__PURE__ */ __name(() => {
|
|
171
|
-
try {
|
|
172
|
-
const isWindows = process.platform === "win32";
|
|
173
|
-
if (isWindows) {
|
|
174
|
-
if (process.env.WT_SESSION)
|
|
175
|
-
return "windows_terminal";
|
|
176
|
-
const shell = process.env.COMSPEC?.toLowerCase() || "";
|
|
177
|
-
if (/powershell/i.test(shell))
|
|
178
|
-
return "powershell";
|
|
179
|
-
if (/pwsh/i.test(shell))
|
|
180
|
-
return "powershell";
|
|
181
|
-
if (/cmd\.exe/i.test(shell))
|
|
182
|
-
return "cmd";
|
|
183
|
-
if (/wt\.exe/i.test(shell))
|
|
184
|
-
return "windows_terminal";
|
|
185
|
-
if (/conhost\.exe/i.test(shell))
|
|
186
|
-
return "conhost";
|
|
187
|
-
return "windows_cmd";
|
|
188
|
-
}
|
|
189
|
-
const terminal = (0, import_node_child_process.execSync)("echo $TERM", {
|
|
190
|
-
encoding: "utf8",
|
|
191
|
-
timeout: 1000,
|
|
192
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
193
|
-
}).trim().toLowerCase();
|
|
194
|
-
return terminal ? terminal.replace(/[^a-z0-9]+/g, "_") : null;
|
|
195
|
-
} catch {
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
}, "detectFromShell");
|
|
199
|
-
var detectFromProcessTitle = /* @__PURE__ */ __name(() => {
|
|
200
|
-
const processTitle = process.title?.toLowerCase() ?? "";
|
|
201
|
-
if (/^alacritty/.test(processTitle))
|
|
202
|
-
return "alacritty";
|
|
203
|
-
if (/^kitty/.test(processTitle))
|
|
204
|
-
return "kitty";
|
|
205
|
-
if (/^wezterm/.test(processTitle))
|
|
206
|
-
return "wezterm";
|
|
207
|
-
if (/^hyper/.test(processTitle))
|
|
208
|
-
return "hyper";
|
|
209
|
-
if (/bash/.test(processTitle))
|
|
210
|
-
return "bash";
|
|
211
|
-
if (/zsh/.test(processTitle))
|
|
212
|
-
return "zsh";
|
|
213
|
-
if (/ksh/.test(processTitle))
|
|
214
|
-
return "ksh";
|
|
215
|
-
if (/fish/.test(processTitle))
|
|
216
|
-
return "fish";
|
|
217
|
-
if (/csh/.test(processTitle))
|
|
218
|
-
return "csh";
|
|
219
|
-
if (/tcsh/.test(processTitle))
|
|
220
|
-
return "tcsh";
|
|
221
|
-
if (/pwsh/.test(processTitle))
|
|
222
|
-
return "powershell";
|
|
223
|
-
if (/powershell/.test(processTitle))
|
|
224
|
-
return "powershell";
|
|
225
|
-
if (/cmd/.test(processTitle))
|
|
226
|
-
return "cmd";
|
|
227
|
-
if (/sh$/.test(processTitle))
|
|
228
|
-
return "sh";
|
|
229
|
-
if (/^node/.test(processTitle))
|
|
230
|
-
return "node";
|
|
231
|
-
return null;
|
|
232
|
-
}, "detectFromProcessTitle");
|
|
233
|
-
var detectTerminal = /* @__PURE__ */ __name(() => {
|
|
234
|
-
let terminal = detectFromEnv();
|
|
235
|
-
if (!terminal) {
|
|
236
|
-
terminal = detectFromShell();
|
|
237
|
-
}
|
|
238
|
-
if (!terminal) {
|
|
239
|
-
terminal = detectFromProcessTitle();
|
|
240
|
-
}
|
|
241
|
-
return terminal || "unknown";
|
|
242
|
-
}, "detectTerminal");
|
|
243
|
-
var detect_terminal_default = detectTerminal;
|
|
244
|
-
});
|
|
245
|
-
|
|
246
21
|
// node_modules/shellwords/lib/shellwords.js
|
|
247
22
|
var require_shellwords = __commonJS((exports) => {
|
|
248
23
|
(function() {
|
|
@@ -3727,7 +3502,7 @@ var require_version = __commonJS((exports) => {
|
|
|
3727
3502
|
});
|
|
3728
3503
|
|
|
3729
3504
|
// node_modules/uuid/dist/index.js
|
|
3730
|
-
var
|
|
3505
|
+
var require_dist = __commonJS((exports) => {
|
|
3731
3506
|
Object.defineProperty(exports, "__esModule", {
|
|
3732
3507
|
value: true
|
|
3733
3508
|
});
|
|
@@ -3807,7 +3582,7 @@ var require_toaster = __commonJS((exports, module) => {
|
|
|
3807
3582
|
var utils = require_utils();
|
|
3808
3583
|
var Balloon = require_balloon();
|
|
3809
3584
|
var os = __require("os");
|
|
3810
|
-
var { v4: uuid } =
|
|
3585
|
+
var { v4: uuid } = require_dist();
|
|
3811
3586
|
var EventEmitter = __require("events").EventEmitter;
|
|
3812
3587
|
var util = __require("util");
|
|
3813
3588
|
var fallback;
|
|
@@ -3956,8 +3731,9 @@ import { basename } from "path";
|
|
|
3956
3731
|
|
|
3957
3732
|
// src/config.ts
|
|
3958
3733
|
import { readFileSync, existsSync } from "fs";
|
|
3959
|
-
import { join } from "path";
|
|
3734
|
+
import { join, dirname } from "path";
|
|
3960
3735
|
import { homedir } from "os";
|
|
3736
|
+
import { fileURLToPath } from "url";
|
|
3961
3737
|
var DEFAULT_EVENT_CONFIG = {
|
|
3962
3738
|
sound: true,
|
|
3963
3739
|
notification: true
|
|
@@ -3967,7 +3743,6 @@ var DEFAULT_CONFIG = {
|
|
|
3967
3743
|
notification: true,
|
|
3968
3744
|
timeout: 5,
|
|
3969
3745
|
showProjectName: true,
|
|
3970
|
-
suppressWhenFocused: false,
|
|
3971
3746
|
command: {
|
|
3972
3747
|
enabled: false,
|
|
3973
3748
|
path: "",
|
|
@@ -4035,7 +3810,6 @@ function loadConfig() {
|
|
|
4035
3810
|
notification: globalNotification,
|
|
4036
3811
|
timeout: typeof userConfig.timeout === "number" && userConfig.timeout > 0 ? userConfig.timeout : DEFAULT_CONFIG.timeout,
|
|
4037
3812
|
showProjectName: userConfig.showProjectName ?? DEFAULT_CONFIG.showProjectName,
|
|
4038
|
-
suppressWhenFocused: typeof userConfig.suppressWhenFocused === "boolean" ? userConfig.suppressWhenFocused : DEFAULT_CONFIG.suppressWhenFocused,
|
|
4039
3813
|
command: {
|
|
4040
3814
|
enabled: typeof userCommand.enabled === "boolean" ? userCommand.enabled : DEFAULT_CONFIG.command.enabled,
|
|
4041
3815
|
path: typeof userCommand.path === "string" ? userCommand.path : DEFAULT_CONFIG.command.path,
|
|
@@ -4080,10 +3854,17 @@ function getMessage(config, event) {
|
|
|
4080
3854
|
function getSoundPath(config, event) {
|
|
4081
3855
|
return config.sounds[event];
|
|
4082
3856
|
}
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
3857
|
+
function getIconPath() {
|
|
3858
|
+
try {
|
|
3859
|
+
const __filename2 = fileURLToPath(import.meta.url);
|
|
3860
|
+
const __dirname2 = dirname(__filename2);
|
|
3861
|
+
const iconPath = join(__dirname2, "..", "logos", "opencode-logo-dark.png");
|
|
3862
|
+
if (existsSync(iconPath)) {
|
|
3863
|
+
return iconPath;
|
|
3864
|
+
}
|
|
3865
|
+
} catch {}
|
|
3866
|
+
return;
|
|
3867
|
+
}
|
|
4087
3868
|
|
|
4088
3869
|
// src/notify.ts
|
|
4089
3870
|
var import_node_notifier = __toESM(require_node_notifier(), 1);
|
|
@@ -4102,7 +3883,7 @@ if (platform === "Linux" || platform.match(/BSD$/)) {
|
|
|
4102
3883
|
platformNotifier = import_node_notifier.default;
|
|
4103
3884
|
}
|
|
4104
3885
|
var lastNotificationTime = {};
|
|
4105
|
-
async function sendNotification(title, message, timeout) {
|
|
3886
|
+
async function sendNotification(title, message, timeout, iconPath) {
|
|
4106
3887
|
const now = Date.now();
|
|
4107
3888
|
if (lastNotificationTime[message] && now - lastNotificationTime[message] < DEBOUNCE_MS) {
|
|
4108
3889
|
return;
|
|
@@ -4122,7 +3903,7 @@ async function sendNotification(title, message, timeout) {
|
|
|
4122
3903
|
title,
|
|
4123
3904
|
message,
|
|
4124
3905
|
timeout,
|
|
4125
|
-
icon:
|
|
3906
|
+
icon: iconPath
|
|
4126
3907
|
};
|
|
4127
3908
|
platformNotifier.notify(notificationOptions, () => {
|
|
4128
3909
|
resolve();
|
|
@@ -4132,11 +3913,11 @@ async function sendNotification(title, message, timeout) {
|
|
|
4132
3913
|
|
|
4133
3914
|
// src/sound.ts
|
|
4134
3915
|
import { platform as platform2 } from "os";
|
|
4135
|
-
import { join as join2, dirname } from "path";
|
|
4136
|
-
import { fileURLToPath } from "url";
|
|
3916
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
3917
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4137
3918
|
import { existsSync as existsSync2 } from "fs";
|
|
4138
3919
|
import { spawn } from "child_process";
|
|
4139
|
-
var __dirname2 =
|
|
3920
|
+
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
4140
3921
|
var DEBOUNCE_MS2 = 1000;
|
|
4141
3922
|
var lastSoundTime = {};
|
|
4142
3923
|
function getBundledSoundPath(event) {
|
|
@@ -4251,20 +4032,6 @@ function runCommand2(config, event, message) {
|
|
|
4251
4032
|
}
|
|
4252
4033
|
|
|
4253
4034
|
// src/index.ts
|
|
4254
|
-
var TERMINAL_PROCESS_NAMES = {
|
|
4255
|
-
ghostty: "Ghostty",
|
|
4256
|
-
kitty: "kitty",
|
|
4257
|
-
iterm: "iTerm2",
|
|
4258
|
-
iterm2: "iTerm2",
|
|
4259
|
-
wezterm: "WezTerm",
|
|
4260
|
-
alacritty: "Alacritty",
|
|
4261
|
-
terminal: "Terminal",
|
|
4262
|
-
apple_terminal: "Terminal",
|
|
4263
|
-
hyper: "Hyper",
|
|
4264
|
-
warp: "Warp",
|
|
4265
|
-
vscode: "Code",
|
|
4266
|
-
"vscode-insiders": "Code - Insiders"
|
|
4267
|
-
};
|
|
4268
4035
|
function getNotificationTitle(config, projectName) {
|
|
4269
4036
|
if (config.showProjectName && projectName) {
|
|
4270
4037
|
return `OpenCode (${projectName})`;
|
|
@@ -4275,14 +4042,9 @@ async function handleEvent(config, eventType, projectName, elapsedSeconds) {
|
|
|
4275
4042
|
const promises = [];
|
|
4276
4043
|
const message = getMessage(config, eventType);
|
|
4277
4044
|
if (isEventNotificationEnabled(config, eventType)) {
|
|
4278
|
-
if (config.suppressWhenFocused) {
|
|
4279
|
-
const shouldSuppress = await isTerminalFocused();
|
|
4280
|
-
if (shouldSuppress) {
|
|
4281
|
-
return;
|
|
4282
|
-
}
|
|
4283
|
-
}
|
|
4284
4045
|
const title = getNotificationTitle(config, projectName);
|
|
4285
|
-
|
|
4046
|
+
const iconPath = getIconPath();
|
|
4047
|
+
promises.push(sendNotification(title, message, config.timeout, iconPath));
|
|
4286
4048
|
}
|
|
4287
4049
|
if (isEventSoundEnabled(config, eventType)) {
|
|
4288
4050
|
const customSoundPath = getSoundPath(config, eventType);
|
|
@@ -4295,76 +4057,6 @@ async function handleEvent(config, eventType, projectName, elapsedSeconds) {
|
|
|
4295
4057
|
}
|
|
4296
4058
|
await Promise.allSettled(promises);
|
|
4297
4059
|
}
|
|
4298
|
-
async function runExecCommand(command, args) {
|
|
4299
|
-
return new Promise((resolve) => {
|
|
4300
|
-
execFile(command, args, (error, stdout) => {
|
|
4301
|
-
if (error) {
|
|
4302
|
-
resolve(null);
|
|
4303
|
-
return;
|
|
4304
|
-
}
|
|
4305
|
-
resolve(stdout.trim());
|
|
4306
|
-
});
|
|
4307
|
-
});
|
|
4308
|
-
}
|
|
4309
|
-
async function runOsascript(script) {
|
|
4310
|
-
if (process.platform !== "darwin")
|
|
4311
|
-
return null;
|
|
4312
|
-
return runExecCommand("osascript", ["-e", script]);
|
|
4313
|
-
}
|
|
4314
|
-
async function getFrontmostAppMac() {
|
|
4315
|
-
return runOsascript('tell application "System Events" to get name of first application process whose frontmost is true');
|
|
4316
|
-
}
|
|
4317
|
-
async function getFrontmostProcessWindows() {
|
|
4318
|
-
if (process.platform !== "win32")
|
|
4319
|
-
return null;
|
|
4320
|
-
const script = [
|
|
4321
|
-
'Add-Type @"',
|
|
4322
|
-
"using System;",
|
|
4323
|
-
"using System.Runtime.InteropServices;",
|
|
4324
|
-
"public class Win32 {",
|
|
4325
|
-
' [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();',
|
|
4326
|
-
' [DllImport("user32.dll")] public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId);',
|
|
4327
|
-
"}",
|
|
4328
|
-
'"@',
|
|
4329
|
-
"$hwnd = [Win32]::GetForegroundWindow()",
|
|
4330
|
-
"$pid = 0",
|
|
4331
|
-
"[Win32]::GetWindowThreadProcessId($hwnd, [ref]$pid) | Out-Null",
|
|
4332
|
-
"(Get-Process -Id $pid).ProcessName"
|
|
4333
|
-
].join(`
|
|
4334
|
-
`);
|
|
4335
|
-
return runExecCommand("powershell", ["-NoProfile", "-Command", script]);
|
|
4336
|
-
}
|
|
4337
|
-
function getTerminalProcessName(terminalName) {
|
|
4338
|
-
return TERMINAL_PROCESS_NAMES[terminalName.toLowerCase()] ?? terminalName;
|
|
4339
|
-
}
|
|
4340
|
-
function normalizeAppName(value) {
|
|
4341
|
-
return value.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
4342
|
-
}
|
|
4343
|
-
function matchesTerminal(frontmost, terminal) {
|
|
4344
|
-
const frontNormalized = normalizeAppName(frontmost);
|
|
4345
|
-
const terminalNormalized = normalizeAppName(terminal);
|
|
4346
|
-
if (!frontNormalized || !terminalNormalized)
|
|
4347
|
-
return false;
|
|
4348
|
-
return frontNormalized.includes(terminalNormalized) || terminalNormalized.includes(frontNormalized);
|
|
4349
|
-
}
|
|
4350
|
-
async function isTerminalFocused() {
|
|
4351
|
-
const terminalName = import_detect_terminal.default({ preferOuter: true });
|
|
4352
|
-
if (!terminalName)
|
|
4353
|
-
return false;
|
|
4354
|
-
if (process.platform === "darwin") {
|
|
4355
|
-
const frontmost = await getFrontmostAppMac();
|
|
4356
|
-
const processName = getTerminalProcessName(terminalName);
|
|
4357
|
-
return frontmost ? frontmost.toLowerCase() === processName.toLowerCase() : false;
|
|
4358
|
-
}
|
|
4359
|
-
if (process.platform === "win32") {
|
|
4360
|
-
const frontmostProcess = await getFrontmostProcessWindows();
|
|
4361
|
-
return frontmostProcess ? matchesTerminal(frontmostProcess, terminalName) : false;
|
|
4362
|
-
}
|
|
4363
|
-
if (process.platform === "linux") {
|
|
4364
|
-
return false;
|
|
4365
|
-
}
|
|
4366
|
-
return false;
|
|
4367
|
-
}
|
|
4368
4060
|
function getSessionIDFromEvent(event) {
|
|
4369
4061
|
const sessionID = event?.properties?.sessionID;
|
|
4370
4062
|
if (typeof sessionID === "string" && sessionID.length > 0) {
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mohak34/opencode-notifier",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18-beta.1",
|
|
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",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"dist",
|
|
20
|
-
"sounds"
|
|
20
|
+
"sounds",
|
|
21
|
+
"logos"
|
|
21
22
|
],
|
|
22
23
|
"scripts": {
|
|
23
24
|
"build": "bun build src/index.ts --outdir dist --target node",
|
|
@@ -32,7 +33,6 @@
|
|
|
32
33
|
"alerts"
|
|
33
34
|
],
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"detect-terminal": "^2.0.0",
|
|
36
36
|
"node-notifier": "^10.0.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|